DoubleLockedQueue
来源:互联网 发布:租人软件app 编辑:程序博客网 时间:2024/06/05 07:27
/************************************************************************* > File Name: DoubleLockedQueue.h > Author: wangzhicheng > Mail: 2363702560@qq.com > Created Time: 2017-01-02 > Statement: double locked concurrent queue ************************************************************************/#ifndef DOUBLE_LOCKED_QUEUE_H#define DOUBLE_LOCKED_QUEUE_H#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <assert.h>#include <atomic>#include <mutex>namespace doublelockedqueue{using namespace std;static const int MAXCAP = 1000000000;/* * the Node of queue * */template<class DataType>class QueueNode{public:DataType m_Data; // pointer to the data which needed to be put in the queueQueueNode<DataType>*m_pNext; // the next pointerQueueNode() {m_pNext = NULL;}QueueNode(const DataType &data, QueueNode *next = NULL) {m_Data = data;m_pNext = next;}~QueueNode() {m_pNext = NULL;}};/* * double locked queue * */template<class DataType>class DoubleLockedQueue {private:mutex m_Head_Lock;// for dequeuemutex m_Tail_Lock;// for enqueueQueueNode<DataType> *m_pHead;QueueNode<DataType> *m_pTail;atomic<int>m_nNum; // 用于计数int m_nMaxLen; // 队列最大长度public:DoubleLockedQueue();/* * @brief 初始化队列容量和头结点 * */void Init(int max);/* * @brief 入队 * @return 入队成功返回true 失败返回false 失败是指队列为满 * */bool EnQueue(const DataType &);/* * @brief 出队 * @return 出队成功返回true 失败返回false 失败是指队列为空 * */bool DeQueue(DataType &);/* * @brief 析构函数 释放头结点 * */~DoubleLockedQueue();};template<class DataType>DoubleLockedQueue<DataType>::DoubleLockedQueue(){m_nNum = 0;}/* * @brief 初始化队列容量和头结点 * */template<class DataType>void DoubleLockedQueue<DataType>::Init(int max) {assert(max > 0 && max <= MAXCAP);m_nMaxLen = max;/* * generate a head node * */m_pHead = new QueueNode<DataType>;m_pTail = this->m_pHead;}template<class DataType>bool DoubleLockedQueue<DataType>::EnQueue(const DataType &data) {if(m_nNum.load() >= m_nMaxLen) // 队列满了{return false;}QueueNode<DataType>*p = new QueueNode<DataType>(data);++m_nNum;/* * 入队与出队的竞争仅仅发生在当队列为空时 * 此时读尾指针与修改尾指针不会同时进行 * 但gcc/g++编译器能够保证对64位地址修改为原子操作 * 例如假设地址A = NULL * 线程1读取A 线程2修改A * 那么线程1要么读到NULL 要么读到线程2修改后的地址 * */lock_guard<mutex>lockguard(m_Tail_Lock);m_pTail->m_pNext = p;m_pTail = p;return true;}template<class DataType>bool DoubleLockedQueue<DataType>::DeQueue(DataType &data){m_Head_Lock.lock();QueueNode<DataType>*p = m_pHead;QueueNode<DataType>*newhead = m_pHead->m_pNext;// 此时取头结点的next指针 可能此时入队修改了头结点的next值 但这两个操作不会并行if(!newhead) { // the queue is emptym_Head_Lock.unlock();return false;}data = newhead->m_Data;m_pHead = newhead;m_Head_Lock.unlock();--m_nNum; delete p;p = NULL;return true;}template<class DataType>DoubleLockedQueue<DataType>::~DoubleLockedQueue(){delete m_pHead;m_pHead = NULL;m_pTail = NULL;}}#endif/************************************************************************* > File Name: main.cpp > Author: wangzhicheng > Mail: 2363702560@qq.com > Created Time: Sat 31 Dec 2016 09:44:59 AM AWST ************************************************************************/#include "DoubleLockedQueue.h"#include <iostream>#include <thread>using namespace doublelockedqueue;DoubleLockedQueue<int>Q;void func0() {while(1){for(int i = 0;i < 10;i++) Q.EnQueue(i);sleep(1);}}void func1() {while(1){int num;if(!Q.DeQueue(num)) {//cerr << "dequeue error...!" << endl;sleep(1);continue;}else cout << "num = " << num << endl;}}int main(){Q.Init(100);thread th1(func0);thread th2(func1);th1.join();th2.join();return 0;}CC=g++all:$(CC) -std=c++11 -g -o DoubleLockedQueueTest main.cpp DoubleLockedQueue.h -pthread -lpthread
0 0