c++实现简易线程池

线程池介绍

线程池是一种基于池化思想管理和使用线程的机制。它是将多个线程预先进行创建,分配任务时,可以避免频繁创建和销毁线程所带来性能开销,只需要取出相应的线程执行对应的任务即可。

简易线程池基本构造

管理线程:

        管理线程需要对工作线程的状态和任务进行管理,保证线程池能够正常运行。

工作线程:

        工作线程需要完成分配给自己的任务,在没有任务的时候尽量少的占用系统资源。

线程任务:

        任务需要包含任务参数和任务函数入口以及其它需要记录的量,添加任务后由管理线程分配给空闲的工作线程

简易线程池实现

最优线程数

        需要控制各线程对线程池内变量的访问,避免造成多条线程同时访问同一变量,同时也要防止线程死锁的发生。工作线程数量控制也要有要求,太少或太多都会导致运行效率达不到预期,为了提高对cpu资源的利用率可以动态的创建和摧毁线程以维持最优线程数量。

对于最优线程数量有以下公式:

        最优线程数量 = CPU核数 * (任务总耗时 / 任务总cpu运行时间)

        即对于一定数量的任务,cpu空闲时间越多,就可以分配更多的线程,反之就应该摧毁一定数量线程以维持最优线程数量,保证不对效率产生影响。

        但是记录cpu运行时间以及对线程频繁的创建摧毁会占用相当一部分的额外资源,同时也会提升一定的实现难度。

        在此可以将线程池管理类型简单的分为以下三种:

        1、IO密集型:

                 主要使用IO收发数据后再使用cpu处理,如:套接字通信、文件读取等在IO处耗时较高的任务,对此可以将线程数量限制为cpu核数的10倍。

        2、CPU密集型:

                主要使用cpu处理再通过IO等进行其它操作,如:压缩文件等,cpu的运行耗时较高同时也有一定IO操作的任务,对此可以将数量限制为cpu核数的2倍。

         3、仅CPU型:

                只使用cpu进行处理的任务,直接限制为cpu核数即可。

                以上这三种管理类型可以适配大部分的简单需求,对于更复杂的需求,使用动态的线程数量管理虽然会占用额外资源,但其适配的效果会更好。

工作线程

        讲到线程必须得先了解一下thread类,thread类是在c++14加入的一个线程类型。其构造函数如下:

template <class _Fn, class... _Args, enable_if_t<!is_same_v<_Remove_cvref_t<_Fn>, thread>, int> = 0>
    _NODISCARD_CTOR explicit thread(_Fn&& _Fx, _Args&&... _Ax)

构造时需提供线程入口,以及入口参数列表,如果是类的非静态成员函数还需要提供一个该类的实例。如果不提供线程入口,虽然可以创建线程变量,但实际上并没用创建新的线程。

由此延伸出一个问题:线程池本身的目的是为了做到线程复用,减少频繁创建、销毁线程造成的开销。如果一开始仅仅创建了变量,在分配任务时再提供线程入口,本质上是与不使用线程池管理时没有区别的,甚至还会多出一部分开销。所以在此可以使用一个固定入口点,让线程进入后不断检测是否有新的任务。同时,为了保证能够让线程能够“访问”自己的任务,还需要有个自定义的线程类,即方便任务的分配又方便线程的管理。

自定义线程类Thread如下:

class Thread {     //线程类,用于执行任务函数,并在任务完成后进行回调。
	private:
		unsigned int id;//线程id
		thread main;//线程本体
		ThreadTask* task = NULL;//线程任务
		bool free = true;//空闲中标志
		bool function = true;//运行中标志
        //这里说明一下 free 和 function 是不冲突的
        //free标识是否有任务,function标识线程是否正常运行
	public:
		Thread(ThreadPool&);//依托线程池的构造函数(因为必须有线程池,所以不需要无参构造)
		bool GiveTask(ThreadTask&);//给线程分配一个任务
		bool Handle(ThreadTask&);//任务处理函数 返回值:是否有任务 参数:线程任务
		bool Handle(ThreadTask**);//同上
		bool Function();//是否运行中
		bool Free();//是否空闲中
		bool Done();//完成任务
		bool Shutdown();//停止
		unsigned int ID();//获取线程ID
	};

因为线程id删除了很多保存的方式,此处提供一个我保存线程id的方法:

id = static_cast<unsigned int>(std::hash<std::thread::id>()(main.get_id()));

这样你就成功创建了一个工作线程的自定义类,但是它的任务该怎么办呢?

函数的参数是类型和数量都不固定的,该如何对任务进行处理以达到参数的正常转发呢?
这个问题目前我想到的有两种方案:

第一种:通过泛型来实现任务函数的完美转发,该种方案需要线程创建时指定参数类型,这样就相当于限制了每个线程能运行的函数,这个方案目前我没有好的想法来实现,有思路的大佬们可以教一下我。

第二种:通过规定任务函数的格式达到效果,可以使用一个空返回值参数为空类型指针的函数来实现参数的传递,通过对空类型指针不断转类型和移动可以做到对数据的读写操作。

void (*_FUNC_)(void*);

但是这样的实现方法势必会导致预处理和后处理占用较多的额外的资源。对此,我使用参数列表来使用简易元组来进行自动封包、解包,可以减少一定的额外资源占用。

	template<typename...An>
	class Meta {};
	template<typename T>
	class Meta<T> {
	public:
		T value;
		static const int length = sizeof(T);
		static const int count = 1;
		Meta(void* ptr, T v) :value(std::move(v)) {
			//std::cout << "Address:\t" << (long long)ptr << "\t -> \t" << v << std::endl;
			*((T*)ptr) = v;
		};
	};
	template<typename T, typename...An>
	class Meta<T, An...> :public Meta<An...>
	{
	public:
		typedef Meta<An...> base;
		T value;
		static const int length = base::length + sizeof(T);
		static const int count = base::count + 1;
		Meta(void* ptr, T v, An...args) :base(((char*)ptr + sizeof(T)), args...), value(std::move(v)) {
			//std::cout << "Address:\t" << (long long)ptr << "\t -> \t" << v << std::endl;
			*((T*)ptr) = v;
		}
	};
	template<int N, class T, class...An>
	class MetaInfo {

	};
	template<class T, class...An>
	class MetaInfo<0, Meta<T, An...>> {
	public:
		typedef typename T Type;
		static const int Offset = 0;
		MetaInfo(void* ptr) {

		}
	};
	template<int N, class T, class...An>
	class MetaInfo<N, Meta<T, An...>> {
	public:
		typedef MetaInfo<N - 1, Meta<An...>> base;
		typedef typename base::Type Type;
		static const int Offset = base::Offset + sizeof(T);
		MetaInfo(void* ptr) :MetaInfo<N - 1, Meta<An...>>(ptr) {

		}
	};

这个元组可以实现对可变模板参数的封包和解包操作,相对于对void*的操作,现在可以更方便、更快的读取到所需的参数,极大化了线程任务的适用范围。其封、解包实例如下:

template<class T, class ...An>
void Func(T s, An... args) {
	int count = Meta<T, An...>::count, length = Meta<T, An...>::length;
	void* ptr = new char(length);
	Meta<T, An...>a(ptr, s, args...);
	for (int i = 0; i < length; i++)
		std::cout << (unsigned int)*((char*)ptr + i) << ' ';
	std::cout << std::endl;
	const int ind = 5;
	int offset = MetaInfo<ind, Meta<T, An...>>::Offset;
	typedef MetaInfo<ind, Meta<T, An...>>::Type TEMP;
	std::cout << "Index " << ind << " is:" << *(TEMP*)((char*)ptr + offset) << std::endl;
}

这样我们就完成了对数据的封包解包,接下来是实现线程任务类ThreadTask。

	enum class TaskState {   //任务状态枚举类,表示任务的不同状态。
		free,		//空闲 - 未执行
		operating,	//运行 - 运行中
		completed,	//完成 - 已运行结束
		error,		//运行中异常
		unknow		//未知 - 状态未知,可能是空任务或异常任务
	};
	class ThreadTask {      //线程任务类,存储了任务的相关信息,包括任务函数、回调函数、异常回调、参数等。
	public:
		//分配的线程ID
		unsigned int tid;
		//任务函数
		void (*_FUNC_)(void*);
		//回调函数
		void (*_CALL_BACK_)(ThreadTask&);
		//异常回调
		void (*_ERROR_CALL_BACK_)(std::exception&);
		//运行参数
		void* _PARAMETERS_;
		//任务状态
		TaskState _TASK_STATE_;
		//错误信息
		std::exception _ERROR_INFO_;
		//13位时间戳
		long _START_TIME_STRAMP_;
		//13位时间戳 完成时间 未完成则为-1
		long _END_TIME_STRAMP_;

		//可以根据传入的参数来初始化对象的各个成员变量。Empty方法用于判断任务是否为空,通过检查任务函数指针、开始时间戳和任务状态来确定任务是否为空任务。

		ThreadTask()
		{
			this->tid = 0;
			this->_FUNC_ = 0;
			this->_CALL_BACK_ = 0;
			this->_ERROR_CALL_BACK_ = 0;
			this->_PARAMETERS_ = 0;
			this->_TASK_STATE_ = TaskState::unknow;
			this->_START_TIME_STRAMP_ = -1;
		}
		ThreadTask(void (*func)(void*), void (*callback)(ThreadTask&), void (*error_callback)(std::exception&), void* parameters, TaskState task_state, long timestramp) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_PARAMETERS_ = parameters;
			this->_TASK_STATE_ = task_state;
			this->_START_TIME_STRAMP_ = timestramp;
		}
		ThreadTask(void (*func)(void*), void (*callback)(ThreadTask&), void (*error_callback)(std::exception&), void* parameters, TaskState task_state) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_PARAMETERS_ = parameters;
			this->_TASK_STATE_ = task_state;
			this->_START_TIME_STRAMP_ = 0;
		}
		template<class Fc,class T, class...An>
		ThreadTask(Fc&& func, void (*callback)(ThreadTask&), void (*error_callback)(std::exception&),T&& _arg,An&&...args) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_TASK_STATE_ = TaskState::free;
			this->_START_TIME_STRAMP_ = 0;
			this->_PARAMETERS_ = new char(Meta<T, An...>::length);
			Meta<T, An...>a(this->_PARAMETERS, _arg, args...);
		}
		~ThreadTask() {
			if (this->_PARAMETERS_)
				delete this->_PARAMETERS_;
		}
		bool Empty() {
			if (!this)
				return true;
			return (this->_FUNC_ == NULL || this->_START_TIME_STRAMP_ < 0 || _TASK_STATE_ == TaskState::unknow);
		}
		//Zero是一个静态成员方法,返回一个初始化为默认值的ThreadTask对象。
		static ThreadTask Zero() {
			return ThreadTask(NULL, NULL, NULL, NULL, TaskState::unknow, -1);
		}
		//ChangeState方法用于修改任务的状态。
		void ChangeState(TaskState state) {
			this->_TASK_STATE_ = state;
		}

完成了封包解包,接下来就是完善我们的Tasker函数,让工作线程真正开始工作

void Tasker() {
			Thread* param = NULL;
			unsigned int id = static_cast<unsigned int>(std::hash<std::thread::id>()(std::this_thread::get_id()));
		GetParam:
            //先找到自己
			lock_parameters.lock();
			for (auto i = list.begin(); i != list.end(); i++) {
				auto _id = (*i)->ID();
				if (_id == id) {
					param = &(**i);
					break;
				}
			}
			lock_parameters.unlock();
			if (!param)
				goto GetParam;

            //加入空闲队列 否则不安排任务
			lock_free.lock();
			free.push(param);
			lock_free.unlock();

            //检查是否有任务
			ThreadTask* task = NULL;
			while (param->Function()) {
				if (CheckSignal) {
                    //此处用于管理线程同步管理线程
					param->Done();
					lock_free.lock();
					//std::cout << std::this_thread::get_id() << " Check!" << std::endl;
					free.push(param);
					lock_free.unlock();
				}
                //获取可能存在的任务
				if (!param->Handle(&task) || !task) {
					std::this_thread::sleep_for(chrono::milliseconds(500));
					continue;
				}

                //任务执行以及简易异常处理
				task->tid = id;
				task->_TASK_STATE_ = TaskState::operating;
				try {
					task->_FUNC_(task->_PARAMETERS_);
					if (task->_CALL_BACK_)
						task->_CALL_BACK_(*task);
					task->ChangeState(TaskState::completed);
				}
				catch (...) {
					try {
						if (!task->_ERROR_CALL_BACK_)
							task->_ERROR_CALL_BACK_(e);
					}
					catch (...) {}
					task->_TASK_STATE_ = TaskState::error;
				}
                
                //完成任务的后处理
				param->Done();
				lock_inuse.lock();
				inuse -= 1;
				lock_inuse.unlock();
				lock_free.lock();
				free.push(param);
				lock_free.unlock();

                //减少频繁调用 否则会占用很多额外资源
				std::this_thread::sleep_for(chrono::milliseconds(500));
			}
		}

由此我们成功的完成了我们的工作线程。

管理线程

跟工作线程一样,一开始就应该让它也进入一个Manager函数中,不断对所有线程进行管理

        void CheckInUse() {
			lock_free.lock();
			std::cout << "Free thread count:" << free.size();
			std::cout << " Inuse:" << inuse;
			std::cout << " Task:" << tasks.size() << "    " << '\r';
			lock_free.unlock();
			if (inUse.size() == 0)
				return;
		}
		const int ManagerTimespan = 0;
		void Manager() {
			lock_inuse.lock();
			inuse = 0;
			lock_inuse.unlock();
			ThreadTask task;
			Thread* th;
			while (function) {
				CheckInUse();
				if (inuse >= count || tasks.size() == 0) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}
                //检查管理数量是否异常
				lock_free.lock();
				if (inuse + free.size() != count) {
					CheckSignal = true;
					std::cout << "List error start to check!" << std::endl;
					while (free.size() != 0)
						free.pop();
				}
				else {
					CheckSignal = false;
				}
				lock_free.unlock();

				//获取任务队列
				lock_queue.lock();
				task = tasks.front();
				tasks.pop();
				lock_queue.unlock();
				if (task.Empty()) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}

				//获取线程队列
				while (free.size() == 0) {
					CheckInUse();
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
				}
				lock_free.lock();
				th = free.front();
				free.pop();
				lock_free.unlock();
				if (!th->Function() || !th->Free()) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}

				//分配任务并加入"运行中"列表
				lock_inuse.lock();
				inuse += 1;
				lock_inuse.unlock();
				th->GiveTask(task);
				inUse.push_back(&task);

				std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
			}

在Manager中可以加入健壮性更强的线程状态管理,也可以加入动态的线程数量不断维持线程数在最优线程数范围之内,总之Manager还有很多可以扩展的功能,可以修改它以适配自己的需求。

 完整代码

至此,一个简易线程池的全部拼图已经被我们逐个找到,将它们全部拼接起来就得到了一个简单的线程池。

#pragma once
#include <thread>
#include <exception>
#include <vector>
#include <mutex>
#include <queue>
#include "UTools.hpp"
//跨平台核数检测
#ifndef __linux__
#include <windows.h>
SYSTEM_INFO sysInfo;
#else
#include "unistd.h"
#include "sys/sysinfo.h"
#endif
using namespace std;
using namespace Tools;
namespace Tools {
#define THREAD_DEFAULT_LIMIT 10
	template<typename...An>
	class Meta {};
	template<typename T>
	class Meta<T> {
	public:
		T value;
		static const int length = sizeof(T);
		static const int count = 1;
		Meta(void* ptr, T v) :value(std::move(v)) {
			//std::cout << "Address:\t" << (long long)ptr << "\t -> \t" << v << std::endl;
			*((T*)ptr) = v;
		};
	};
	template<typename T, typename...An>
	class Meta<T, An...> :public Meta<An...>
	{
	public:
		typedef Meta<An...> base;
		T value;
		static const int length = base::length + sizeof(T);
		static const int count = base::count + 1;
		Meta(void* ptr, T v, An...args) :base(((char*)ptr + sizeof(T)), args...), value(std::move(v)) {
			//std::cout << "Address:\t" << (long long)ptr << "\t -> \t" << v << std::endl;
			*((T*)ptr) = v;
		}
	};
	template<int N, class T, class...An>
	class MetaInfo {

	};
	template<class T, class...An>
	class MetaInfo<0, Meta<T, An...>> {
	public:
		typedef typename T Type;
		static const int Offset = 0;
		MetaInfo(void* ptr) {

		}
	};
	template<int N, class T, class...An>
	class MetaInfo<N, Meta<T, An...>> {
	public:
		typedef MetaInfo<N - 1, Meta<An...>> base;
		typedef typename base::Type Type;
		static const int Offset = base::Offset + sizeof(T);
		MetaInfo(void* ptr) :MetaInfo<N - 1, Meta<An...>>(ptr) {

		}
	};
	enum class TaskState {   //任务状态枚举类,表示任务的不同状态。
		free,		//空闲 - 未执行
		operating,	//运行 - 运行中
		completed,	//完成 - 已运行结束
		error,		//运行中异常
		unknow		//未知 - 状态未知,可能是空任务或异常任务
	};
	class ThreadTask {      //线程任务类,存储了任务的相关信息,包括任务函数、回调函数、异常回调、参数等。
	public:
		//分配的线程ID
		unsigned int tid;
		//任务函数
		void (*_FUNC_)(void*);
		//回调函数
		void (*_CALL_BACK_)(ThreadTask&);
		//异常回调
		void (*_ERROR_CALL_BACK_)(std::exception&);
		//运行参数
		void* _PARAMETERS_;
		//任务状态
		TaskState _TASK_STATE_;
		//错误信息
		std::exception _ERROR_INFO_;
		//13位时间戳
		long _START_TIME_STRAMP_;
		//13位时间戳 完成时间 未完成则为-1
		long _END_TIME_STRAMP_;

		//可以根据传入的参数来初始化对象的各个成员变量。Empty方法用于判断任务是否为空,通过检查任务函数指针、开始时间戳和任务状态来确定任务是否为空任务。

		ThreadTask()
		{
			this->tid = 0;
			this->_FUNC_ = 0;
			this->_CALL_BACK_ = 0;
			this->_ERROR_CALL_BACK_ = 0;
			this->_PARAMETERS_ = 0;
			this->_TASK_STATE_ = TaskState::unknow;
			this->_START_TIME_STRAMP_ = -1;
		}
		ThreadTask(void (*func)(void*), void (*callback)(ThreadTask&), void (*error_callback)(std::exception&), void* parameters, TaskState task_state, long timestramp) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_PARAMETERS_ = parameters;
			this->_TASK_STATE_ = task_state;
			this->_START_TIME_STRAMP_ = timestramp;
		}
		ThreadTask(void (*func)(void*), void (*callback)(ThreadTask&), void (*error_callback)(std::exception&), void* parameters, TaskState task_state) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_PARAMETERS_ = parameters;
			this->_TASK_STATE_ = task_state;
			this->_START_TIME_STRAMP_ = 0;
		}
		template<class Fc,class T, class...An>
		ThreadTask(Fc&& func, void (*callback)(ThreadTask&), void (*error_callback)(std::exception&),T&& _arg,An&&...args) {
			this->tid = 0;
			this->_FUNC_ = func;
			this->_CALL_BACK_ = callback;
			this->_ERROR_CALL_BACK_ = error_callback;
			this->_TASK_STATE_ = TaskState::free;
			this->_START_TIME_STRAMP_ = 0;
			this->_PARAMETERS_ = new char(Meta<T, An...>::length);
			Meta<T, An...>a(this->_PARAMETERS, _arg, args...);
		}
		~ThreadTask() {
			if (this->_PARAMETERS_)
				delete this->_PARAMETERS_;
		}
		bool Empty() {
			if (!this)
				return true;
			return (this->_FUNC_ == NULL || this->_START_TIME_STRAMP_ < 0 || _TASK_STATE_ == TaskState::unknow);
		}
		//Zero是一个静态成员方法,返回一个初始化为默认值的ThreadTask对象。
		static ThreadTask Zero() {
			return ThreadTask(NULL, NULL, NULL, NULL, TaskState::unknow, -1);
		}
		//ChangeState方法用于修改任务的状态。
		void ChangeState(TaskState state) {
			this->_TASK_STATE_ = state;
		}
	};
	enum class PoolType {
		CPUDense = 0,
		CPUOnly = 1,
		IODense = 2
	};
	class ThreadPool;  //线程池类,管理线程和任务队列,并根据需要进行任务分配。
	class Thread {     //线程类,用于执行任务函数,并在任务完成后进行回调。
	private:
		unsigned int id;
		thread main;
		ThreadTask* task = NULL;
		bool free = true;
		bool function = true;
	public:
		Thread(ThreadPool&);
		bool GiveTask(ThreadTask&);
		bool Handle(ThreadTask&);
		bool Handle(ThreadTask**);
		bool Function();
		bool Free() {
			return free;
		}
		bool Done() {
			task = NULL;
			free = true;
			return free;
		}
		bool Shutdown();
		unsigned int ID();
	};
	class ThreadPool {
	private:
		int limit, count, inuse;
		vector<Thread*> list;
		queue<Thread*> free;//排队领任务
		vector<ThreadTask*> inUse;
		queue<ThreadTask> tasks;
		thread manager;
		PoolType type;
		mutex lock_parameters, lock_queue, lock_free, lock_inuse;
		bool function = true;
	public:
		//-1无限制 且取反为0
		ThreadPool(PoolType type, int limit = -1) {
			if (limit != 0 && limit >= -1)
				this->limit = limit;
			else
				this->limit = THREAD_DEFAULT_LIMIT;
			if (~this->limit)
				this->count = limit;
			else
			{
				this->type = type;
#ifndef __linux__
				//cpu密集型 2*核数加一(一条管理线程)
				if (type == PoolType::CPUDense)
				{
					GetSystemInfo(&sysInfo);
					this->count = 2 * sysInfo.dwNumberOfProcessors;
				}
				//仅cpu运算 核数
				else if (type == PoolType::CPUOnly) {
					GetSystemInfo(&sysInfo);
					this->count = sysInfo.dwNumberOfProcessors;
				}
				//IO密集型 10*核数 - 1
				else if (type == PoolType::IODense) {
					GetSystemInfo(&sysInfo);
					this->count = 10 * sysInfo.dwNumberOfProcessors - 1;
				}
				else
					this->count = 4;
				this->limit = this->count;
#else
				//同上
				if (type == PoolType::CPUDense)
				{
					GetSystemInfo(&sysInfo);
					this->count = 2 * sysconf(_SC_NPROCESSORS_CONF);
				}
				else if (type == PoolType::CPUOnly) {
					GetSystemInfo(&sysInfo);
					this->count = sysconf(_SC_NPROCESSORS_CONF);
				}
				else if (type == PoolType::IODense) {
					GetSystemInfo(&sysInfo);
					this->count = 10 * sysconf(_SC_NPROCESSORS_CONF) - 1;
				}
				else
					this->count = 4;
				this->limit = this->count;
#endif
			}
			for (int i = 0; i < this->count; i++) {
				lock_parameters.lock();
				Thread* temp = new Thread(*this);
				list.push_back(temp);
				lock_parameters.unlock();
			}
			manager = thread(&ThreadPool::Manager, this);
		}
		~ThreadPool() {

		}
		bool CheckSignal = false;
		void Tasker() {
			Thread* param = NULL;
			unsigned int id = static_cast<unsigned int>(std::hash<std::thread::id>()(std::this_thread::get_id()));
		GetParam:
			lock_parameters.lock();
			for (auto i = list.begin(); i != list.end(); i++) {
				auto _id = (*i)->ID();
				if (_id == id) {
					param = &(**i);
					break;
				}
			}
			lock_parameters.unlock();
			if (!param)
				goto GetParam;
			lock_free.lock();
			free.push(param);
			std::cout << "Thread:" << param->ID() << " in queue!" << std::endl;
			lock_free.unlock();
			ThreadTask* task = NULL;
			while (param->Function()) {
				if (CheckSignal) {
					param->Done();
					lock_free.lock();
					//std::cout << std::this_thread::get_id() << " Check!" << std::endl;
					free.push(param);
					lock_free.unlock();
				}
				if (!param->Handle(&task) || !task) {
					std::this_thread::sleep_for(chrono::milliseconds(500));
					continue;
				}

				task->tid = id;
				task->_TASK_STATE_ = TaskState::operating;
				try {
					task->_FUNC_(task->_PARAMETERS_);
					if (task->_CALL_BACK_)
						task->_CALL_BACK_(*task);
					task->ChangeState(TaskState::completed);
				}
				catch (std::exception e) {
					try {
						if (!task->_ERROR_CALL_BACK_)
							task->_ERROR_CALL_BACK_(e);
					}
					catch (std::exception e) {}
					task->_TASK_STATE_ = TaskState::error;
				}
				param->Done();
				lock_inuse.lock();
				inuse -= 1;
				lock_inuse.unlock();
				lock_free.lock();
				//std::cout << std::this_thread::get_id() << " Free" << std::endl;
				free.push(param);
				lock_free.unlock();

				std::this_thread::sleep_for(chrono::milliseconds(500));
			}
		}
		void CheckInUse() {
			lock_free.lock();
			std::cout << "Free thread count:" << free.size();
			std::cout << " Inuse:" << inuse;
			std::cout << " Task:" << tasks.size() << "    " << '\r';
			lock_free.unlock();
			if (inUse.size() == 0)
				return;
		}
		const int ManagerTimespan = 0;
		void Manager() {
			lock_inuse.lock();
			inuse = 0;
			lock_inuse.unlock();
			ThreadTask task;
			Thread* th;
			while (function) {
				CheckInUse();
				if (inuse >= count || tasks.size() == 0) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}
				lock_free.lock();
				//if (inuse + free.size() != count) {
				//	CheckSignal = true;
				//	std::cout << "List error start to check!" << std::endl;
				//	while (free.size() != 0)
				//		free.pop();
				//}
				//else {
				//	CheckSignal = false;
				//}
				lock_free.unlock();

				//获取任务队列
				lock_queue.lock();
				task = tasks.front();
				tasks.pop();
				lock_queue.unlock();
				if (task.Empty()) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}

				//获取线程队列
				while (free.size() == 0) {
					CheckInUse();
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
				}
				lock_free.lock();
				th = free.front();
				free.pop();
				lock_free.unlock();
				if (!th->Function() || !th->Free()) {
					std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
					continue;
				}

				//分配任务并加入"运行中"列表
				lock_inuse.lock();
				inuse += 1;
				lock_inuse.unlock();
				th->GiveTask(task);
				inUse.push_back(&task);

				std::this_thread::sleep_for(chrono::milliseconds(ManagerTimespan));
			}
		}
		void AddTask(ThreadTask task) {
			lock_queue.lock();
			tasks.push(task);
			lock_queue.unlock();
		}
		void AddTask(void(*func)(void*), void* parameters) {
			lock_queue.lock();
			tasks.push(ThreadTask(func, NULL, NULL, parameters, TaskState::free));
			lock_queue.unlock();
		}
		template<class Fc, class...An>
		void AddTask(Fc&& func, An... args) {
			lock_queue.lock();
			tasks.push(ThreadTask(func, NULL, NULL, args));
			lock_queue.unlock();
		}
	};

	Thread::Thread(ThreadPool& pool) {
		main = thread(&ThreadPool::Tasker, &pool);
		id = static_cast<unsigned int>(std::hash<std::thread::id>()(main.get_id()));
		main.detach();
	}
	bool Thread::GiveTask(ThreadTask& task) {
		if (!free || task.Empty())
			return false;
		this->task = &task;
		return true;
	}
	bool Thread::Handle(ThreadTask& task) {
		task = ThreadTask::Zero();
		if (!free || this->task->Empty())
			return false;
		free = false;
		task = *(this->task);
		this->task = NULL;
		return true;
	}
	bool Thread::Handle(ThreadTask** task) {
		*task = NULL;
		if (!free || this->task->Empty())
			return false;
		free = false;
		*task = this->task;
		this->task = NULL;
		return true;
	}
	bool Thread::Function() {
		return function;
	}
	bool Thread::Shutdown() {
		function = false;
		return function;
	}
	unsigned int Thread::ID() {
		return id;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值