C++ 九阴真经之异步队列

异步队列可以看作是消息队列和线程池的合体,输入端是用户自定义数据,输出端为用户自定义执行体。

定义类型

        T

定义执行体 

        bool task(T& t){}

就可以实现没每一个消息执行操作

        task(t)

/************************************************************************************
* 异步队列
* 用户将数据压入队列,并自定义执行函数,对数据进行异步处理
* T 数据类型
* RET 结果返回类型
************************************************************************************/
template <typename T, typename RET>
struct NodeData
{
	T data;
	std::promise<RET> res;
};
 
template<typename T, typename RET>
class CAsyncQueue : public ThreadObject
{
public:
	void Start(unsigned short nThreadNum, std::function<RET(T)> f)
	{
		m_idlThrNum = nThreadNum < 1 ? 1 : nThreadNum;
		for (auto size = 0; size < nThreadNum; ++size)
		{   //初始化线程数量
			m_pThreadPool.emplace_back(
				[this, f]
			{ // 工作线程函数
				while (!this->m_bStop)
				{
					NodeData<T, RET> task;
					{   // 获取一个待执行的 task
						// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
						std::unique_lock<std::mutex> lock(m_mu);
 
						this->m_condPop.wait(lock,
							[this] {
							return this->m_bStop.load() || !this->m_taskQueue.empty();
						}
						); // wait 直到有 task
						if (this->m_bStop && this->m_taskQueue.empty())
							return;
						task = std::move(this->m_taskQueue.front()); // 取一个 task
						this->m_taskQueue.pop();
					}
					//通知写线程
					m_condPush.notify_one();
					m_idlThrNum--;
					task.res.set_value(f(task.data));
					m_idlThrNum++;
				}
			}
			);
		}
	}
 
	//向队列中压入任务
	std::future<RET> Push(T val)
	{
		std::promise<RET> prs;
		auto ret = prs.get_future();
 
 
		{
			std::unique_lock<std::mutex> lock(m_mu);
 
			//不允许向已停止的线程池提交作业
			if (m_bStop)
				throw std::runtime_error("向已停止的线程工厂提交作业");
 
			while (m_taskQueue.size() == m_nCapacity)         //队列已满
			{
				m_condPush.wait(m_mu);                         //等待,将暂时的解锁
			}
 
			m_taskQueue.emplace(NodeData<T, RET>{ val, std::move(prs) });
		}
 
		m_condPop.notify_one(); // 唤醒一个线程执行
		return ret;
	}
 
	virtual size_t GetTaskNum()
	{
		return m_taskQueue.size();
	}
 
 
private:
	std::queue<NodeData<T, RET>> m_taskQueue;                    //队列
};

测试代码

int main()
{
    CAsyncQueue<std::string, bool> sqlQueue;
	sqlQueue.Start(1, [](const std::string& sql) {
		std::cout << sql << std::endl;
		return true;
	});
 
	sqlQueue.Push("select * from db;");
	auto ret = sqlQueue.Push("delete from db;");
	if (ret.get())
	{
		std::cout << "执行成功" << std::endl;
	}
 
	std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值