线程池的思想早有耳闻,中间也涉及好多内容,回过头来重新设计一下线程池.
使用者视角:
1.创建一个线程池对象, ThreadPool ThPool(int minThreads); //同时会创建一个管理者线程,负责维护线程池,可以通过算法动态调度增加或减少线程
2.加入一个任务 int ThPool.PushTask((void*)(*)(void),bool ifneedResult=false); //如果不需要返回结果性能更好,返回一个key查询任务执行状态
3.根据key得到任务执行结果 struct Result GetResult(int key) //返回一个结果结构体,要求调用者先检查状态码,再使用val值
enum Status{OK=0,BUSYING,TODO,NOSCUHTASK,ERROR,} //任务状态 ----> 正常结束,忙,尚未执行,无此任务,出错
struct Result{
Status flag;
void * val;
}
目标要求:
1.涉及的互斥锁,条件变量,信号量全部使用c++11特性,方便在windows和linux下通用
2.GetResult这个函数我有过诸多考虑,比如 通常实现都是对一个简单结果表上锁,获得锁,查询结果,再释放锁. 但是,这样做有一个小问题,
每一个单独Thread在完成任务后都要把结果放入
//这其中也看过别人的线程池,不过绝大多数都是简单实现,我这个也不过是简单级里的复杂版....日后可能会对这个线程池进行改进
//这方面应该去看看Nginx这种工业级线程池实现......
比较长,所以分几部分,第一部分是 循环队列模板
#ifndef _LOOP_QUEUE #define _LOOP_QUEUE #pragma once template<class T> //push满了会false,空pop会返回0,没有扩容 class Loop_Queue { int m_capacity; T* arr; int front, rear; bool autoExpansion = false; //自动扩容....TODO public: explicit Loop_Queue(int capacity); ~Loop_Queue(); bool Push(const T&val); T Pop(); int GetSize(); int GetCapacity(); bool Empty(); }; #endif // !_LOOP_QUEUE template<class T> Loop_Queue<T>::Loop_Queue(int capacity) { m_capacity = capacity; arr = new T[m_capacity + 1]; front = rear = 0; } template<class T> inline bool Loop_Queue<T>::Push(const T&val) { if (rear != m_capacity) { //判断满 if (rear == front - 1) return false; } else { if (front == 0) return false; } arr[rear] = val; //插入 if (rear == m_capacity) //尾部 rear = 0; else ++rear; return true; } template<class T> T Loop_Queue<T>::Pop() //为空返回(T)0,用前先判断为空最好,想了下还是不抛异常好,虽然STL是这样做 { if (front == rear) return T(0); if (front != m_capacity) return arr[front++]; else { front = 0; return arr[m_capacity]; } } template<class T> int Loop_Queue<T>::GetSize() { if (front < rear) { return rear - front; } else { return rear + (m_capacity - front); } return 0; } template<class T> inline int Loop_Queue<T>::GetCapacity() { return m_capacity; } template<class T> inline bool Loop_Queue<T>::Empty() { if (front == rear) return true; else return false; } template<class T> inline Loop_Queue<T>::~Loop_Queue() { delete[] arr; }
循环队列 模板几个要点: 队列唯一的构造函数是整形的有参构造,指定最大队列长度(元素数量)
当队列满时push操作会返回false,正常返回true, 当队列已经为空的时候返回T(0),强制要求模板T类型有int转换构造函数
比如采用下面这个任务结构体
typedef struct Task_t{ int key; void* (*work)(void*); void* arg; inline explicit Task_t(const int a=0) { //使得可以(T)5 这样使用,或者T(5); key = a; work = NULL; arg = NULL; } }Task_t;