C++ 封装线程池(结合QT支持信号机制)

15 篇文章 0 订阅
1 篇文章 0 订阅

纯C++风格线程池

纯C++ 风格线程池可参考这篇文章

https://llfc.club/category?catid=225RaiVNI8pFDD5L4m807g7ZwmF#!aid/2c2IJUcCUOfzEQQRRdOXYIZuCjP

视频教程

相关线程池和并发编程的视频可以看看这个连接:

https://www.bilibili.com/video/BV1Xt421H7M7/?vd_source=8be9e83424c2ed2c9b2a3ed1d01385e9

支持信号机制的线程池

我的项目中期待封装一个类,内部有个线程池处理外部投递的内容,这个类同时支持对外发送信号等,同时这个类是一个单例类,那么这个类可以继承QOjbject支持信号机制,并且其内部可以封装一个线程池响应外部投递的任务,结合纯C++版本封装了如下在QT环境使用的线程池,目前已经投入到生产中。

用到的头文件

#include <QObject>
#include <queue>
#include <vector>
#include <thread>
#include <queue>
#include <memory>
#include <functional>
#include <mutex>
#include <atomic>
#include <future>

头文件编写

#ifndef SEQSCHEDULER_H
#define SEQSCHEDULER_H
//wwc 处理维护,关机流程,清洗等时序执行的类
class SeqScheduler: public QObject
{
	Q_OBJECT
public:
    ~ SeqScheduler();
	static SeqScheduler& Inst();
	template<typename F, typename ... Args>
	auto CommitTask(F&& func, Args && ... args) ->
		std::future<decltype(std::forward<F>(func)(std::forward<Args>(args)...))> {
		using RetType = decltype(std::forward<F>(func)(std::forward<Args>(args)...));
		if (_b_stop.load()) {
			return std::future<RetType>{};
		}

		auto bind_func = std::bind(std::forward<F>(func), std::forward<Args>(args)...);

		auto pack_task = std::make_shared<std::packaged_task<RetType(void)>>(bind_func);
		auto future = pack_task->get_future();
		{
			std::lock_guard<std::mutex> lock(_work_mtx);
			_work_que.push([pack_task]() {
				(*pack_task)();
				});
		}

		_work_con.notify_one();
		return future;
	}


private: 
	SeqScheduler(const SeqScheduler&) = delete;
	SeqScheduler& operator = (const SeqScheduler&) = delete;
	SeqScheduler(unsigned int num = std::thread::hardware_concurrency());
	std::queue<std::function<void(void)>> _work_que;
	std::mutex _work_mtx;
	std::condition_variable _work_con;
	std::atomic<bool>  _b_stop;
	std::vector<std::thread> _pool;
	std::atomic_int          _thread_num;
};

#endif // SEQSCHEDULER_H

类的具体实现

#include "seqscheduler.h"

SeqScheduler::SeqScheduler(unsigned int num ): _b_stop(false)
{
	if (num <= 1)
		_thread_num = 1;
	else
		_thread_num = num;

	for (int i = 0; i < _thread_num; i++) {
		_pool.emplace_back([this]() {
			for (; !(_b_stop.load());) {
				std::unique_lock<std::mutex> unique_locker(_work_mtx);
				_work_con.wait(unique_locker, [this]() {
					if (_b_stop.load()) {
						return true;
					}

					if (_work_que.empty()) {
						return false;
					}

					return true;
					});

				if (_b_stop.load()) {
					return;
				}

				//出队
				auto task = _work_que.front();
				_work_que.pop();
				unique_locker.unlock();
				task();
			}
			});
	}

}

SeqScheduler& SeqScheduler::Inst()
{
	static SeqScheduler inst;
	return inst;
}

SeqScheduler::~SeqScheduler(){
	_b_stop = true;
	{
		std::unique_lock<std::mutex> unique_locker(_work_mtx);
		_work_con.notify_all();
	}

	for (auto& td : _pool) {
		if (td.joinable()) {
			std::cout << "join thread " << td.get_id() << std::endl;
			td.join();
		}
	}
}

使用线程池

线程池的使用可以通过如下方式投递任务,任务在后台自动执行

void Test(){
	SeqScheduler::Inst().CommitTask([]() {
		asyncLog("slot machine perfusion called ");
		});
}

如需等待任务完成,可以用wait或者get

void Test(){
	auto task_future = SeqScheduler::Inst().CommitTask([]() {
		asyncLog("slot machine perfusion called ");
		});
	task_future.wait();
}
  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋风辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值