线程池的思想早有耳闻,中间也涉及好多内容,回过头来重新设计一下线程池.
使用者视角:
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;