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

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

定义类型

        T

定义执行体 

        bool task(T& t){}

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

        task(t)

/************************************************************************************
* 异步队列
* 用户将数据压入队列,并自定义执行函数,对数据进行异步处理
* T 数据类型
* RET 结果返回类型
************************************************************************************/
template 
struct NodeData
{
	T data;
	std::promise res;
};

template
class CAsyncQueue : public ThreadObject
{
public:
	void Start(unsigned short nThreadNum, std::function 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 task;
					{   // 获取一个待执行的 task
						// unique_lock 相比 lock_guard 的好处是:可以随时 unlock() 和 lock()
						std::unique_lock 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 Push(T val)
	{
		std::promise prs;
		auto ret = prs.get_future();


		{
			std::unique_lock 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{ val, std::move(prs) });
		}

		m_condPop.notify_one(); // 唤醒一个线程执行
		return ret;
	}

	virtual size_t GetTaskNum()
	{
		return m_taskQueue.size();
	}

 
private:
	std::queue> m_taskQueue;                    //队列
};

测试代码

int main()
{
    CAsyncQueue 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;
}

你可能感兴趣的:(C++,异步队列)