学习内容来自一下地址
http://www.cnblogs.com/qicosmos/p/4772486.html
github https://github.com/qicosmos/cosmos
主要使用c++11的多线程编程的互斥 同步等功能 编写一个生产消费者队列 用于任务的传递
将任务的接受处理进行分离 更加简洁 易于处理和扩展修改
template<typename T> //队列传递的元素 为了适配更多情况 这里使用了模板
class SyncQueue {
...................
}
//初始化函数 定义队列最大可容纳元素数目和停止表示
SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){}
//Put函数即是提价元素 之所以使用两种函数 是考虑左值和右值 提高元素拷贝效率
void Put(const T& x) {
Add(x);
}
void Put(T&& x) {
Add(std::forward<T>(x));
}
//查看Add函数
template<typename F>
void Add(F&& x) {
std::unique_lock<std::mutex> locker(m_mutex); //加锁
m_notFull.wait(locker, [this] {return m_needStop || NotFull(); }); // 使条件变量等待 队列未满或者标记停止标识
if (m_needStop) //停止退出
return;
m_queue.push_back(std::forward<F>(x)); //则将元素添加进容器
m_notEmpty.notify_one();
}
//加锁情况下 使条件变量等待 队列未满或者标记停止标识 则将元素添加进容器或者停止退出
//元素取出函数 一个是取出容器内全部元素 一个是取出单个元素
void Take(std::list<T>& list)
void Take(T& t)
//void Take(std::list<T>& list) 取出容器内全部元素 直接将容器去除 并清除队列内的容器
//代码里直接使用了move函数 并notify Take函数中的条件变量
void Take(std::list<T>& list) {
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop)
return;
list = std::move(m_queue);
m_notFull.notify_one();
}
//void Take(T& t) 加锁情况下 使用条件变量等待停止标识或者容器非空
//将容器内元素弹出 并notify Add函数中的条件变量
void Take(T& t) {
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop)
return;
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
源码如下 (仅仅队列代码,测试代码将同线程池一同测试)
1 #pragma once 2 3 #include <list> 4 #include <mutex> 5 #include <thread> 6 #include <condition_variable> 7 #include <iostream> 8 9 using namespace std; 10 11 template<typename T> 12 class SyncQueue { 13 public: 14 SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){} 15 void Put(const T& x) { 16 Add(x); 17 } 18 void Put(T&& x) { 19 Add(std::forward<T>(x)); 20 } 21 void Take(std::list<T>& list) { 22 std::unique_lock<std::mutex> locker(m_mutex); 23 m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 24 if (m_needStop) 25 return; 26 list = std::move(m_queue); 27 m_notFull.notify_one(); 28 } 29 30 void Take(T& t) { 31 std::unique_lock<std::mutex> locker(m_mutex); 32 m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); }); 33 if (m_needStop) 34 return; 35 t = m_queue.front(); 36 m_queue.pop_front(); 37 m_notFull.notify_one(); 38 } 39 40 void Stop() { 41 { 42 std::lock_guard<std::mutex> locker(m_mutex); 43 m_needStop = true; 44 } 45 m_notFull.notify_all(); 46 m_notEmpty.notify_all(); 47 } 48 49 bool Empty() { 50 std::lock_guard<std::mutex> locker(m_mutex); 51 return m_queue.empty(); 52 } 53 54 bool Full() { 55 std::lock_guard<std::mutex> locker(m_mutex); 56 return m_queue.size() == m_maxSize; 57 } 58 59 size_t Size() { 60 std::lock_guard<std::mutex> locker(m_mutex); 61 return m_queue.size(); 62 } 63 64 int Count() { 65 return m_queue.size(); 66 } 67 private: 68 bool NotFull()const { 69 bool full = m_queue.size() >= m_maxSize; 70 if (full) 71 cout << "buffer area is full,wait..." << endl; 72 return !full; 73 } 74 bool NotEmpty()const { 75 bool empty = m_queue.empty(); 76 if (empty) 77 cout << "buffer area is empty,wait... " << 78 " threadID: " << this_thread::get_id() <<endl; 79 return !empty; 80 } 81 82 template<typename F> 83 void Add(F&& x) { 84 std::unique_lock<std::mutex> locker(m_mutex); 85 m_notFull.wait(locker, [this] {return m_needStop || NotFull(); }); 86 if (m_needStop) 87 return; 88 m_queue.push_back(std::forward<F>(x)); 89 m_notEmpty.notify_one(); 90 } 91 private: 92 std::list<T> m_queue; 93 std::mutex m_mutex; 94 std::condition_variable m_notEmpty; 95 std::condition_variable m_notFull; 96 int m_maxSize; 97 bool m_needStop; 98 };