三种数据队列的实现


   
   



     
     
  1 /**
  2 * 文件名称:dataqueue.h
  3 * 摘    要:本文件实现了三种数据队列:简单队列,单队列类和双数据队列类。
  4             1) 简单队列:使用List库,动态分配内存,使用临界区保证互斥
  5             2)单队列:采用链表实现,一次性分配内存。减少频繁内存申请开销,同样采用临界区保存互斥。
  6             3)双队列:包含两个单队列,采用ping-pong双缓冲策略,使得在多线程应用中,能保证最小的数据交换开销
  7 * 当前版本:1.0
  8 * 作    者:darkhorse
  9 * 完成日期:2014-6-24
 10 **/
 11 
 12 #ifndef __IMPLIMENT_DATA_QUEUE_H__
 13 #define __IMPLIMENT_DATA_QUEUE_H__
 14 
 15 #include <Windows.h>
 16 #include <iostream>
 17 #include <cstdio>
 18 #include <cstdlib>
 19 #include <assert.h>
 20 #include <list>
 21 namespace hw {
 22 
 23     /*!< 队列满时再次分配数据的元素大小*/
 24     #define ONCE_MALLOC_SIZE    10
 25 
 26     typedef enum Result {
 27         NONE,
 28         MEM_ALLOC_FAILED,
 29         MEM_NOT_ENOUGH,
 30         DATA_NOT_EXISTED,
 31 
 32     };
 33 
 34 
 35     /******************************************************************/
 36     template<typename T>
 37     class CSimpleQueue
 38     {
 39     public:
 40         CSimpleQueue()
 41         {
 42             InitializeCriticalSection(&m_crit);
 43         }
 44         ~CSimpleQueue()
 45         {
 46             DeleteCriticalSection(&m_crit);
 47         }
 48 
 49         void pushData(const T &data)
 50         {
 51             EnterCriticalSection(&m_crit);
 52             m_dataList.push_back(data);
 53             LeaveCriticalSection(&m_crit);
 54         }
 55 
 56         BOOL popData(T &data)
 57         {
 58             EnterCriticalSection(&m_crit);
 59             if (m_dataList.size() > 0)
 60             {
 61                 data = m_dataList.front();
 62                 m_dataList.pop_front();
 63                 LeaveCriticalSection(&m_crit);
 64 
 65                 return TRUE;
 66             }
 67             else
 68             {
 69                 LeaveCriticalSection(&m_crit);
 70                 return FALSE;
 71             }
 72         }
 73 
 74     private:
 75         std::list<T> m_dataList;
 76         CRITICAL_SECTION m_crit;
 77     };
 78 
 79 
 80     /*!< 链表元素*/
 81     template<typename T>
 82     struct DataElement
 83     {
 84         T *m_pData;
 85         DataElement *m_pNext;
 86 
 87         DataElement()
 88         {
 89             reset();
 90         }
 91 
 92         void reset()
 93         {
 94             m_pData = NULL;
 95             m_pNext = NULL;
 96         }
 97     };
 98 
 99     /*********************** 单队列类*******************************/
100     template <typename T>
101     class CSingleQueue
102     {
103     public:
104         CSingleQueue(unsigned int nSize = ONCE_MALLOC_SIZE);
105         ~CSingleQueue();
106 
107         void reset();
108         BOOL pushData(const T &data);
109         BOOL popData(const T* &pData);
110         void removeHead();    /*!< 删除一条数据*/
111         unsigned int getLen();
112         BOOL isEmpty();
113 
114     private:
115         BOOL reAlloc();
116         DataElement<T> *m_pHeadPos; /*!< 队列数据头*/
117         DataElement<T> *m_pTailPos; /*!< 队列数据尾*/
118         DataElement<T> *m_pFreePos; /*!< 空闲数据起始位置*/
119 
120         unsigned int m_nMaxSize; /*!< 队列包含的最大数据大小*/
121         unsigned int m_nCurSize; /*!< 队列当前包含的数据元素大小*/
122         T *m_pDataMem; /*!< 指向分配的数据*/
123     };
124 
125     /*!< 类实现*/
126     template<typename T>
127     CSingleQueue<T>::CSingleQueue(unsigned int nSize)
128     {
129         m_pDataMem = new T[nSize];
130         if(NULL == m_pDataMem)
131         {
132             assert(FALSE);
133         }
134         m_nMaxSize = nSize;
135         m_nCurSize = 0;
136         m_pHeadPos = NULL;
137         m_pFreePos = NULL;
138         m_pTailPos = NULL;
139     }
140 
141     template<typename T>
142     CSingleQueue<T>::~CSingleQueue()
143     {
144         reset();
145         while(m_pFreePos != NULL)
146         {
147             DataElement<T> *pTemp = m_pFreePos;
148             m_pFreePos = m_pFreePos->m_pNext;
149             delete pTemp;
150             pTemp = NULL;
151         }
152         m_nCurSize = 0;
153 
154         if(m_pDataMem != NULL)
155         {
156             delete []m_pDataMem;
157             m_pDataMem = NULL;
158         }
159         m_nMaxSize = 0;
160     }
161 
162     /*!< 重置队列*/
163     template<typename T>
164     void CSingleQueue<T>::reset()
165     {
166         while (m_pHeadPos != NULL)
167         {
168             DataElement<T> *pTemp = m_pHeadPos;
169             m_pHeadPos = m_pHeadPos->m_pNext;
170             pTemp->reset();
171             pTemp->m_pNext = m_pFreePos;
172             m_pFreePos = pTemp;
173         }
174         m_nCurSize = 0;
175         m_pTailPos = NULL;
176     }
177 
178     template<typename T>
179     BOOL CSingleQueue<T>::reAlloc()
180     {
181         for (unsigned int i=0; i<ONCE_MALLOC_SIZE; i++)
182         {
183             DataElement<T> *pTemp = new DataElement<T>;
184             if(NULL == pTemp)
185             {
186                 assert(FALSE);
187                 return FALSE;
188             }
189             pTemp->reset();
190             pTemp->m_pNext = m_pFreePos;
191             m_pFreePos = pTemp;
192         }
193         return TRUE;
194     }
195 
196     template<typename T>
197     BOOL CSingleQueue<T>::pushData(const T &data)
198     {
199         if(m_nCurSize >= m_nMaxSize)
200         {
201             return FALSE;
202         }
203 
204         DataElement<T> *pTemp = NULL;
205         if(m_pFreePos != NULL)
206         {
207             pTemp = m_pFreePos;/*!< 找到第一个空闲结点*/
208             m_pFreePos = m_pFreePos->m_pNext;
209         }
210         else
211         {
212             /*!< 如果没有空闲结点,再次分配*/
213             if (reAlloc())
214             {
215                 if(m_pFreePos != NULL)
216                 {
217                     pTemp = m_pFreePos;/*!< 找到第一个空闲结点*/
218                     m_pFreePos = m_pFreePos->m_pNext;
219                 }
220             }
221         }
222         if(pTemp != NULL)
223         {
224             m_pDataMem[m_nCurSize] = data;/*!< 先将数据拷贝到队列内存*/
225             pTemp->reset();
226             pTemp->m_pData = &m_pDataMem[m_nCurSize];/*!< 给数据成员赋值*/
227 
228             if(NULL == m_pHeadPos)
229             {
230                 m_pHeadPos = pTemp;
231             }
232             else
233             {
234                 m_pTailPos->m_pNext = pTemp;
235             }
236             m_pTailPos = pTemp;
237 
238             m_nCurSize++;
239             return TRUE;
240         }
241         return FALSE;
242     }
243 
244     template<typename T>
245     BOOL CSingleQueue<T>::popData(const T* &pData)
246     {
247         DataElement<T> *pTemp = m_pHeadPos;
248         if(pTemp != NULL)
249         {
250             pData = pTemp->m_pData;
251             return TRUE;
252         }
253         return FALSE;
254     }
255 
256     template<typename T>
257     void CSingleQueue<T>::removeHead()
258     {
259         if (m_pHeadPos != NULL)
260         {
261             DataElement<T> *pTemp = m_pHeadPos;
262             m_pHeadPos = m_pHeadPos->m_pNext;
263             pTemp->reset();
264             pTemp->m_pNext = m_pFreePos;
265             m_pFreePos = pTemp;
266             m_nCurSize--;
267         }
268     }
269 
270     template<typename T>
271     unsigned int CSingleQueue<T>::getLen()
272     {
273         return m_nCurSize;
274     }
275 
276     template<typename T>
277     BOOL CSingleQueue<T>::isEmpty()
278     {
279         return (m_pHeadPos == 0) ? TRUE : FALSE;
280     }
281 
282 
283     /****************************双队列类***************************/
284     template<typename T>
285     class CDoubleQueue
286     {
287     public:
288         CDoubleQueue();
289         ~CDoubleQueue();
290 
291         BOOL init(unsigned int nSize);
292         void release();
293 
294         BOOL pushData(const T &data);
295         BOOL popData(const T* &pData);
296         void removeHead();
297     private:
298         CSingleQueue<T> *m_pPushList;
299         CSingleQueue<T> *m_pPopList;
300         CRITICAL_SECTION m_crit;
301     };
302 
303     /*!< 类的实现*/
304     template<typename T>
305     CDoubleQueue<T>::CDoubleQueue()
306     {
307         m_pPushList = NULL;
308         m_pPopList = NULL;
309         InitializeCriticalSection(&m_crit);
310     }
311 
312     template<typename T>
313     CDoubleQueue<T>::~CDoubleQueue()
314     {
315         DeleteCriticalSection(&m_crit);
316     }
317 
318     template<typename T>
319     void CDoubleQueue<T>::release()
320     {
321         if(m_pPushList != NULL)
322         {
323             delete m_pPushList;
324             m_pPushList = NULL;
325         }
326 
327         if(m_pPopList != NULL)
328         {
329             delete m_pPopList;
330             m_pPopList = NULL;
331         }
332     }
333 
334     template<typename T>
335     BOOL CDoubleQueue<T>::init(unsigned int nSize)
336     {
337         if(nSize == 0)
338         {
339             return FALSE;
340         }
341 
342         release();
343         m_pPushList = new CSingleQueue<T>(nSize);
344         if(NULL == m_pPushList)
345         {
346             return FALSE;
347         }
348 
349         m_pPopList = new CSingleQueue<T>(nSize);
350         if(NULL == m_pPopList)
351         {
352             return FALSE;
353         }
354 
355         return TRUE;
356     }
357 
358     template <class T>
359     BOOL CDoubleQueue<T>::pushData(const T &data)
360     {
361         BOOL bSuccess = FALSE;
362         EnterCriticalSection(&m_crit);
363         bSuccess = m_pPushList->pushData(data);
364         LeaveCriticalSection(&m_crit);
365         return bSuccess;
366     }
367 
368     template <class T>
369     BOOL CDoubleQueue<T>::popData(const T* &pData)
370     {
371         BOOL bCouldRead = TRUE;
372         if(m_pPopList->isEmpty())
373         {
374             EnterCriticalSection(&m_crit);
375             if(m_pPushList->isEmpty())
376             {
377                 LeaveCriticalSection(&m_crit);
378                 bCouldRead = FALSE;
379             }
380             else
381             {
382                 m_pPopList->reset();
383                 CSingleQueue<T> *pTemp = m_pPopList;
384                 m_pPopList = m_pPushList;
385                 m_pPushList = pTemp;
386                 LeaveCriticalSection(&m_crit);
387                 bCouldRead = TRUE;
388             }
389         }
390         if (bCouldRead)
391         {
392             return m_pPopList->popData(pData);
393         }
394         else
395         {
396             return FALSE;
397         }
398     }
399 
400     template <class T>
401     void CDoubleQueue<T>::removeHead()
402     {
403         m_pPopList->removeHead();
404     }
405 }
406 #endif

 

  1 #include "dataqueue.h"
  2 #include <process.h>
  3 #include <assert.h>
  4 
  5 using namespace hw;
  6 using namespace std;
  7 
  8 enum queueType {SIMPLEQ, SINGLEQ, DOUBLEQ, QUIT};
  9 
 10 #define QUEUE_SIZE_TEST 50
 11 CSimpleQueue<int> g_simpleQ;
 12 CSingleQueue<int> g_singleQ(QUEUE_SIZE_TEST);
 13 CDoubleQueue<int> g_doubleQ;
 14 
 15 int gWriteCnt_simple = 0;
 16 int gReadCnt_simple = 0;
 17 
 18 int gWriteCnt_single = 0;
 19 int gReadCnt_single = 0;
 20 
 21 int gWriteCnt_double = 0;
 22 int gReadCnt_double = 0;
 23 
 24 bool gReadThreadQuit = false;
 25 bool gWriteThreadQuit = false;
 26 
 27 void read(void *arg)
 28 {
 29     queueType type = (queueType)(*((queueType*)arg));
 30 
 31     while(!gReadThreadQuit)
 32     {
 33         if(type == SIMPLEQ)
 34         {
 35             int data = 0;
 36             g_simpleQ.popData(data);
 37             gReadCnt_simple++;
 38         }
 39         else if(type == SINGLEQ)
 40         {
 41             const int *pData = NULL;
 42             g_singleQ.popData(pData);
 43             g_singleQ.removeHead();
 44             gReadCnt_single++;
 45         }
 46         else if(type == DOUBLEQ)
 47         {
 48             const int *pData = NULL;
 49             g_doubleQ.popData(pData);
 50             g_doubleQ.removeHead();
 51             gReadCnt_double++;
 52         }
 53         else
 54         {
 55             assert(false);
 56             break;
 57         }
 58         Sleep(10);
 59     }
 60     _endthread();
 61 }
 62 
 63 void write(void *arg)
 64 {
 65     queueType type = (queueType)(*((queueType*)arg));
 66 
 67     while(!gWriteThreadQuit)
 68     {
 69         if(type == SIMPLEQ)
 70         {
 71             int data = 0;
 72             g_simpleQ.pushData(data);
 73             gWriteCnt_simple++;
 74         }
 75         else if(type == SINGLEQ)
 76         {
 77             const int data = 0;
 78             g_singleQ.pushData(data);
 79             gWriteCnt_single++;
 80         }
 81         else if(type == DOUBLEQ)
 82         {
 83             const int data = 0;
 84             g_doubleQ.pushData(data);
 85             gWriteCnt_double++;
 86         }
 87         else
 88         {
 89             assert(false);
 90             break;
 91         }
 92         Sleep(10);
 93     }
 94     _endthread();
 95 }
 96 
 97 void printUsage()
 98 {
 99     printf("usage:test.exe [option]\n \
100     option: \
101     0 use simple queue for test\n \
102     1 use single queue for test\n \
103     2 use double queue for test\n \
104     3 quit\n\n");
105 }
106 int main(int argc, char *argv[])
107 {
108     printUsage();
109 
110     while(1)
111     {
112         int opt;
113         printf("please input the option number: ");
114         scanf_s("%1d", &opt);
115         if(opt == (int)SIMPLEQ)
116         {
117 
118         }
119         else if(opt == (int)SINGLEQ)
120         {
121 
122         }
123         else if(opt == (int)DOUBLEQ)
124         {
125             g_doubleQ.init(QUEUE_SIZE_TEST);
126         }
127         else if(opt == (int)QUIT)
128         {
129             break;
130         }
131         else
132         {
133             printf("invalid number\n");
134             continue;
135         }
136 
137         LARGE_INTEGER freq;
138         LARGE_INTEGER startCount, endCount;
139         QueryPerformanceFrequency(&freq);
140         QueryPerformanceCounter(&startCount);
141 
142         HANDLE readHandle = (HANDLE)_beginthread(write, 0, &opt);
143         HANDLE writeHandle = (HANDLE)_beginthread(read, 0, &opt);
144 
145         LONGLONG sec = 0;
146         /*!< run one second*/
147         while((sec -1000) < 0.00001)
148         {
149             QueryPerformanceCounter(&endCount);
150             sec = (endCount.QuadPart - startCount.QuadPart) * 1000 / freq.QuadPart;        
151         }
152 
153         gReadThreadQuit = true;
154         gWriteThreadQuit = true;
155 
156         WaitForSingleObject(readHandle, INFINITE);
157         WaitForSingleObject(writeHandle, INFINITE);
158 
159         gReadThreadQuit = false;
160         gWriteThreadQuit = false;
161 
162         int readCnt = 0;
163         int writeCnt = 0;
164         if ((queueType)opt == SIMPLEQ)
165         {
166             readCnt = gReadCnt_simple;
167             writeCnt = gWriteCnt_simple;
168         }
169         else if((queueType)opt == SINGLEQ)
170         {
171             readCnt = gReadCnt_single;
172             writeCnt = gWriteCnt_single;
173         }
174         else if((queueType)opt == DOUBLEQ)
175         {
176             readCnt = gReadCnt_double;
177             writeCnt = gWriteCnt_double;
178         }
179         printf("write count: %d, read count: %d\n", writeCnt, readCnt);
180     }
181     return 0;
182 }

 

 

参考:https://software.intel.com/zh-cn/blogs/2013/03/21/twoqueues/?utm_campaign=CSDN&utm_source=intel.csdn.net&utm_medium=Link&utm_content=%20Multicore%20%e2%80%93%20TwoQueues

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值