C++的线程安全的队列

 

(1)这个实现要求构建工具支持C++11的atomic mutex condition_veriable功能。这是C++11的基础特性,一般2011年以后的C++编译器都能支持。 例如,visual studio 2012以上。

(2)这个类的实现中有两处使用了unique_lock而不是lock_guard,这是data_cond.wait所需要的,unique_lock是lock_guard的增强版。

通过std::move的使用(前提是我们实现的类型T定义了移动构造函数和移动赋值函数),能利用移动语义带来的性能优势。

使用shared_ptr<T>返回元素,用户无需释放元素的内存。

 

#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <string>
#include <atomic>

using namespace std;

template<typename T>
class threadsafe_queue
{
public:
	threadsafe_queue()
	{
		m_bTermination = false;
	}
	~threadsafe_queue(void)
	{

	}
	//(1)没有调用termination时,每调用一次出队一个元素,直到队列为空本方法阻塞线程。
	//(2)在调用了termination后,本方法永不阻塞,如果原本已经处于阻塞状态,接触阻塞状态。
	//(3)返回true时,value值有效。返回false时,value值无效。调用了termination且队列为空时返回false.
	bool wait_and_pop(T& value)
	{
		unique_lock<mutex> lk(mut);
		data_cond.wait(lk,[this]{return ((!data_queue.empty())||m_bTermination);});
		//不为空则出队
		if (!data_queue.empty())
		{
			value = move(*data_queue.front());
			data_queue.pop();
			return true;
		}
		//队列为空则返回失败
		return false;
	}

	//队列为空返回false
	bool try_pop(T& value)
	{
		lock_guard<mutex> lk(mut);
		if (data_queue.empty())
		{
			return false;
		}
		value = move(*data_queue.front());
		data_queue.pop();
		return true;
	}
	std::shared_ptr<T> wait_and_pop()
	{
		unique_lock<mutex> lk(mut);
		data_cond.wait(lk,[this]{return ((!data_queue.empty())||m_bTermination);});
		if (!data_queue.empty())
		{
			shared_ptr<T> res = data_queue.front();
			data_queue.pop();
			return res;
		}
		return nullptr;
	}
	//队列为空返回null
	std::shared_ptr<T> try_pop()
	{
		lock_guard<mutex> lk(mut);
		if(data_queue.empty())
		{
			return nullptr;
		}
		shared_ptr<T> res = data_queue.front();
		data_queue.pop();
		return res;
	}
	//插入一项
	void push(T new_value)
	{
		if (m_bTermination)
		{
			return;
		}
		shared_ptr<T> data(make_shared<T>(move(new_value)));
		lock_guard<mutex> lk(mut);
		data_queue.push(data);
		data_cond.notify_one();
	}
	bool empty()
	{
		lock_guard<mutex> lk(mut);
		return data_queue.empty();
	}
	int size()
	{
		lock_guard<mutex> lk(mut);
		return data_queue.size();
	}
	//设置队列为退出状态。在退出状态下,忽略入队,可以执行出队,但当队列为空时,wait_and_pop不会阻塞。
	void termination()
	{
                lock_guard<mutex> lk(mut);
		m_bTermination = true;
		data_cond.notify_all();
	}
	//是退出状态吗
	bool is_termination()
	{
		return m_bTermination;
	}
private:
	mutex mut;
	queue<shared_ptr<T>> data_queue;
	condition_variable data_cond;
	atomic<bool> m_bTermination;
};

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值