眉目传情之并发无锁环形队列的实现
-
Author:Echo Chen(陈斌)
-
Email:chenb19870707@gmail.com
-
Date:October 10th, 2014
前面在《眉目传情之匠心独运的kfifo》一文中详细解析了 linux 内核并发无锁环形队列kfifo的原理和实现,kfifo鬼斧神工,博大精深,让人叹为观止,但遗憾的是kfifo为内核提供服务,并未开放出来。剑不试则利钝暗,弓不试则劲挠诬,鹰不试则巧拙惑,马不试则良驽疑,光说不练是不能学到精髓的,下面就动手实现自己的并发无锁队列UnlockQueue(单生产者单消费者)。
一、UnlockQueue声明
1: #ifndef _UNLOCK_QUEUE_H
2: #define _UNLOCK_QUEUE_H
3:
4: class UnlockQueue
5: {
6: public:
7: UnlockQueue(int nSize);
8: virtual ~UnlockQueue();
9:
10: bool Initialize();
11:
12: unsigned int Put(const unsigned char *pBuffer, unsigned int nLen);
13: unsigned int Get(unsigned char *pBuffer, unsigned int nLen);
14:
15: inline void Clean() { m_nIn = m_nOut = 0; }
16: inline unsigned int GetDataLen() const { return m_nIn - m_nOut; }
17:
18: private:
19: inline bool is_power_of_2(unsigned long n) { return (n != 0 && ((n & (n - 1)) == 0)); };
20: inline unsigned long roundup_power_of_two(unsigned long val);
21:
22: private:
23: unsigned char *m_pBuffer; /* the buffer holding the data */
24: unsigned int m_nSize; /* the size of the allocated buffer */
25: unsigned int m_nIn; /* data is added at offset (in % size) */
26: unsigned int m_nOut; /* data is extracted from off. (out % size) */
27: };
28:
29: #endif
UnlockQueue与kfifo 结构相同相同,也是由一下变量组成:
UnlockQueue kfifo 作用 m_pBuffer buffer 用于存放数据的缓存 m_nSize size 缓冲区空间的大小,圆整为2的次幂 m_nIn in 指向buffer中队头 m_nOut out 指向buffer中的队尾 UnlockQueue的设计是用在单生产者单消费者情况下,所以不需要锁 lock 如果使用不能保证任何时间最多只有一个读线程和写线程,必须使用该lock实施同步。 二、UnlockQueue构造函数和初始化
1: UnlockQueue::UnlockQueue(int nSize)
2: :m_pBuffer(NULL)
3: ,m_nSize(nSize)
4: ,m_nIn(0)
5: ,m_nOut(0)
6: {
7: //round up to the next power of 2
8: if (!is_power_of_2(nSize))
9: {
10: m_nSize = roundup_power_of_two(nSize);
11: }
12: }
13:
14: UnlockQueue::~UnlockQueue()
15: {
16: if(NULL != m_pBuffer)