#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <pthread.h> // 导入线程池头文件
#include <list> // 请求队列
#include "locker.h" // 自己写的互斥锁
#include <exception> // 异常throw std::exception();
#include <cstdio>
// 线程池: 找个线程处理任务
// 定义成模板类为了代码的复用,在别的项目中也能用
// 模板参数T是任务类
// 5.5 34:08
// 模板类T唯一需要具有的函数 process()
template<typename T>
class threadpool{
public:
threadpool(int thread_number = 8, int max_requests = 10000); //构造函数
~threadpool(); // 析构函数
bool append(T* request);
private:
static void * worker(void * arg); // 静态的函数,子线程执行的内容,pthread_create中子线程执行的内容
void run();
private:
int m_thread_number;// 线程的数量
pthread_t * m_threads;// 容器装线程:线程池数组,大小为m_thread_number
int m_max_requests; // 请求队列中最多允许的等待处理的请求数量
std::list<T *> m_workqueue; // 请求队列
locker m_queuelocker;// 互斥锁
sem m_queuestat;// 信号量:用来判断是否有任务需要处理
bool m_stop;// 是否结束线程
};
// 成员函数的实现
// 构造函数
template<typename T>
threadpool<T>::threadpool(int thread_number, int max_requests) : // 单冒号,对成员初始化
m_thread_number(thread_number), m_max_requests(max_requests),
m_stop(false),m_threads(NULL){
if(thread_number <= 0 || max_requests <= 0){
throw std::exception();
}
m_threads = new pthread_t[m_thread_number]; // 创建m_thread_number个线程,是一个数组
if(!m_threads){
throw std::exception();
}
// 创建thread_number个线程,并将他们设置为线程脱离。
// 线程脱离,自动释放线程
for(int i = 0; i < thread_number; ++i){
printf("create the %dth thread\n", i); // #include <cstdio.h>
// pthread_create 如果成功了结果返回 0 ,否则非0,可能是状态码
if(pthread_create(m_threads + i, NULL, worker, this) !=0){ // worker是个子线程执行的内容,是一个静态函数,this 传递给worker,worker内就可以使用该对象的成员,如果没有this,
// 因为worker是静态的,无法使用该对象的成员。
delete[] m_threads; // 使用new[] 创建,那么需要使用delete[] 删除
throw std::exception();
}
// 线程分离:设置线程的一种属性,如果该线程执行完毕,那么自动释放该线程的资源
if(pthread_detach(m_threads[i])){
delete[] m_threads;
throw std::exception();
}
}
}
// 析构函数
template<typename T>
threadpool<T>::~threadpool(){
delete[] m_threads;
m_stop = true; // 停止线程
}
// append函数
template<typename T>
bool threadpool<T>::append(T * request){ // 需要写返回值类型
m_queuelocker.lock(); // 上锁
// 超过最大量
if(m_workqueue.size() > m_max_requests){
m_queuelocker.unlock();
return false;
}
m_workqueue.push_back(request);
m_queuelocker.unlock(); // 解锁
m_queuestat.post(); // 队列中增加,信号量增加。根据信号量判断阻塞or执行
return true;
}
// worker函数
template<typename T>
void* threadpool<T>::worker(void * arg){
threadpool * pool = (threadpool *) arg;
pool->run();
return pool;
}
// run函数
template<typename T>
void threadpool<T>::run(){
while(!m_stop){ // run() 一直要执行,直到遇到停止信号
m_queuestat.wait(); // 信号量调用wait();没有值堵在这
m_queuelocker.lock(); // 上锁
if(m_workqueue.empty()){ // 如果空的那么continue到while开始。再次检测
m_queuelocker.unlock();
continue;
}
// 有数据
T * request = m_workqueue.front(); // 取出第一个
m_workqueue.pop_front(); // 删除取出来的那个
m_queuelocker.unlock(); // 解锁以后才能操作
if(! request){
continue;
}
request->process(); // 处理任务 // 模板类T唯一需要具有的函数 process()
}
}
#endif