/*************************************************************************
> File Name: AtomicInteger.h
> Author: wangzhicheng
> Mail: 2363702560@qq.com
> Created Time: 2017-01-03
> statement: provide atomic integer and operation for multithread
************************************************************************/
#ifndef ATOMIC_INTEGER_H
#define ATMOIC_INTEGER_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
namespace atomicinteger
{
using namespace std;
/**
*@brief provide atomic integer and operation for multithread
*/
template<class T>
class AtomicInteger
{
private:
volatile T value; // prevent g++ to optimize the value
public:
AtomicInteger():value(0)
{
}
/*
* @brief get the original value
* */
T GetValue()
{
// if value == 0 then value = 0 and return the original value
return __sync_val_compare_and_swap(&value, 0, 0);
}
/*
* @brief suffix ++ such as a++
* */
T operator ++ (int)
{
return __sync_fetch_and_add(&value, 1);
}
/*
* @brief prefix ++ such as ++a
* */
T operator ++ ()
{
return __sync_add_and_fetch(&value, 1);
}
/*
* @brief 加某个数
* */
T operator + (int num)
{
return __sync_add_and_fetch(&value, num);
}
/*
* @brief 减某个数
* */
T operator - (int num)
{
return __sync_add_and_fetch(&value, -num);
}
/*
* @brief suffix -- such as a--
* */
T operator -- (int)
{
return __sync_fetch_and_add(&value, -1);
}
/*
* @brief prefix -- such as --a
* */
T operator -- ()
{
return __sync_add_and_fetch(&value, -1);
}
/*
* @brief add operation
* */
T operator + (const T &other)
{
return __sync_add_and_fetch(&value, other);
}
/*
* @brief = operation
* */
T operator = (const T &newValue)
{
return __sync_lock_test_and_set(&value, newValue);
}
};//ns
typedef AtomicInteger<uint64_t>AtomicInt64;
typedef AtomicInteger<uint32_t>AtomicInt32;
}
#endif
/*************************************************************************
> File Name: ThreadMutex.h
> Author: wangzhicheng
> Mail: 2363702560@qq.com
> Created Time: 2017-01-03
************************************************************************/
/*
* @brief provide a thread mutex
* */
#ifndef THREADMUTEX_H
#define THREADMUTEX_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
using namespace std;
namespace threadmutex
{
#define CAS __sync_bool_compare_and_swap // define cas
/*
* @brief thread mutex lock
* */
class ThreadMutexLock
{
private:
pthread_mutex_t m_lock; // mutex lock
public:
ThreadMutexLock()
{
pthread_mutex_init(&m_lock, NULL);
}
~ThreadMutexLock()
{
pthread_mutex_destroy(&m_lock);
}
inline void Lock()
{
pthread_mutex_lock(&m_lock);
}
inline void UnLock()
{
pthread_mutex_unlock(&m_lock);
}
};
/*
* @brief thread cas which is suitable for very short critical zone
* */
class ThreadCasLock
{
private:
// lock variables
volatile int m_mutex;
volatile int m_lock;
volatile int m_unlock;
int m_sleeptime;
public:
ThreadCasLock(int sleeptime = 200)
{
m_mutex = 0;
m_lock = 1;
m_unlock = 0;
m_sleeptime = sleeptime;
}
~ThreadCasLock()
{
m_mutex = 0;
m_lock = 1;
m_unlock = 0;
}
inline void Lock()
{
while(!CAS(&m_mutex, m_unlock, m_lock))
{
usleep(m_sleeptime); // wait untill the lock is free usleep(200)
}
}
inline void UnLock()
{
CAS(&m_mutex, m_lock, m_unlock);
}
};
}
#endif
/*************************************************************************
> File Name: SmartQueue.h
> Author: wangzhicheng
> Mail: 2363702560@qq.com
> Created Time: 2017-01-03
> Statement:可限长并发双锁队列 适合多放1出 或多放多出
************************************************************************/
#ifndef SMART_QUEUE_H
#define SMART_QUEUE_H
#include <assert.h>
#include "AtomicInteger.h"
#include "ThreadMutex.h"
namespace smartqueue {
using namespace atomicinteger;
using namespace threadmutex;
const static int S_MAXLEN_QUEUE = 100000000; // 该队列结点数上限
/*
* the Node of queue, the element of Node is pointer
* */
template<class DataType>
class QueueNode
{
public:
DataType m_Data; // pointer to the data which needed to be put in the queue
QueueNode<DataType>*m_pNext; // the next pointer
public:
QueueNode()
{
this->m_pNext = NULL;
}
QueueNode(const DataType &data, QueueNode *next = NULL)
{
this->m_Data = data;
this->m_pNext = next;
}
~QueueNode()
{
this->m_pNext = NULL;
}
};
/*
* double locked queue
* */
template<class DataType>
class SmartQueue
{
private:
ThreadCasLock m_Head_Lock; // 适合多放1出
ThreadCasLock m_Tail_Lock;
QueueNode<DataType>*m_pHead;
QueueNode<DataType>*m_pTail;
AtomicInt32 m_nNum; // 用于计数
int m_nMaxLen; // 队列最大长度
public:
SmartQueue(int sleeptime);
/*
* @brief 初始化队列容量和头结点
* */
void Init(int max);
/*
* @brief 入队
* @return 入队成功返回true 失败返回false 失败是指队列为满
* */
bool EnQueue(const DataType &);
/*
* @brief 出队
* @return 出队成功返回true 失败返回false 失败是队列为空
* */
bool DeQueue(DataType &);
/*
* @brief 判断队列是不是满
* @return 满返回true 不满返回false
* */
inline bool Full();
/*
* @brief 判断队列是不是为空
* @return 为空返回true
* */
inline bool Empty();
/*
* @brief 析构函数 释放头结点
* */
~SmartQueue();
};
template<class DataType>
SmartQueue<DataType>::SmartQueue(int sleeptime):m_Head_Lock(sleeptime), m_Tail_Lock(sleeptime)
{
}
/*
* @brief 初始化队列容量和头结点
* */
template<class DataType>
void SmartQueue<DataType>::Init(int max)
{
assert(max < S_MAXLEN_QUEUE && max > 0);
m_nMaxLen = max;
/*
* generate a head node
* */
m_pHead = new QueueNode<DataType>;
m_pTail = m_pHead;
}
template<class DataType>
bool SmartQueue<DataType>::EnQueue(const DataType &data)
{
if(m_nNum.GetValue() >= (unsigned int)(this->m_nMaxLen)) // 队列满了
{
return false;
}
QueueNode<DataType>*p = new QueueNode<DataType>(data);
/*
* 入队与出队的竞争仅仅发生在当队列为空时
* 此时读尾指针与修改尾指针不会同时进行
* 但gcc/g++编译器能够保证对64位地址修改为原子操作
* 例如假设地址A = NULL
* 线程1读取A 线程2修改A
* 那么线程1要么读到NULL 要么读到线程2修改后的地址
* */
m_Tail_Lock.Lock();
m_pTail->m_pNext = p;
m_pTail = p;
m_Tail_Lock.UnLock();
++this->m_nNum;
return true;
}
template<class DataType>
bool SmartQueue<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 empty
{
m_Head_Lock.UnLock();
return false;
}
data = newhead->m_Data;
m_pHead = newhead;
m_Head_Lock.UnLock();
--this->m_nNum;
delete p;
p = NULL;
return true;
}
template<class DataType>
inline bool SmartQueue<DataType>::Full()
{
return m_nNum.GetValue() >= (unsigned int)m_nMaxLen;
}
template<class DataType>
inline bool SmartQueue<DataType>::Empty()
{
return m_nNum.GetValue() <= 0; // 队列空
}
template<class DataType>
SmartQueue<DataType>::~SmartQueue()
{
delete this->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 <iostream>
#include <vector>
#include <thread>
#include <chrono>
#include "SmartQueue.h"
using namespace std;
using namespace smartqueue;
SmartQueue<int>Q(10);
void func0()
{
chrono::milliseconds dura(1000);
while(1)
{
for(int i = 0;i < 10;i++)
{
if(!Q.EnQueue(i))
{
cerr << i << " enqueue failed...!" << endl;
}
}
// this_thread::sleep_for(dura);
}
}
void func1()
{
chrono::milliseconds dura(1);
while(1)
{
int num;
if(!Q.DeQueue(num))
{
// cerr << "dequeue failed...!" << endl;
this_thread::sleep_for(dura);
}
else cout << "num = " << num << endl;
}
}
int main()
{
Q.Init(5);
thread th1(func0);
// thread th2(func1);
vector<thread>th2s;
for(int i = 0;i < 100;i++)
{
th2s.push_back(thread(func1));
}
th1.join();
for(auto &th:th2s)
{
th.join();
}
// th2.join();
return 0;
}
CC=g++
all:
$(CC) -std=c++11 -g -o ConCurrentQueueTest main.cpp AtomicInteger.h ThreadMutex.h SmartQueue.h -pthread -lpthreadsmart queue
最新推荐文章于 2023-09-21 15:45:17 发布

1565

被折叠的 条评论
为什么被折叠?



