#pragma once
#include<queue>
#include<pthread.h>
using namespace std;
using callback =void(*)(void* arg);
template<typename T>
struct Task{
Task(){
function =nullptr;
arg=nullptr;
}
Task(callback f,void* arg){
this->arg=(T*)arg;
function=f;
}
void (*function)(void* arg);
T* arg;
};
template<typename T>
class TaskQueue{
public:
TaskQueue();
~TaskQueue();
void addTask(Task<T> task);
void addTask(callback f,void* arg);
Task<T> takeTask();
inline int taskNumber(){
return m_taskQ.size();
}
private:
pthread_mutex_t m_mutex;
std::queue<Task<T>> m_taskQ;
};
#include "TaskQueue.h"
template<typename T>
TaskQueue<T>::TaskQueue(){
pthread_mutex_init(&m_mutex,NULL);
}
template<typename T>
TaskQueue<T>::~TaskQueue(){
pthread_mutex_destroy(&m_mutex);
}
template<typename T>
void TaskQueue<T>::addTask(Task<T> task){
pthread_mutex_lock(&m_mutex);
m_taskQ.push(task);
pthread_mutex_unlock(&m_mutex);
}
template<typename T>
void TaskQueue<T>::addTask(callback f,void* arg){
pthread_mutex_lock(&m_mutex);
m_taskQ.push(Task<T>(f,arg));
pthread_mutex_unlock(&m_mutex);
}
template<typename T>
Task<T> TaskQueue<T>::takeTask(){
Task<T> t;
pthread_mutex_lock(&m_mutex);
if(!m_taskQ.empty()){
t=m_taskQ.front();
m_taskQ.pop();
}
pthread_mutex_unlock(&m_mutex);
return t;
}
#pragma once
#include "TaskQueue.h"
#include<pthread.h>
template<typename T>
class ThreadPool{
public:
ThreadPool(int min,int max);
~ThreadPool();
void addTask(Task<T> task);
int getbusyNum();
int getliveNum();
private:
static void* worker(void *arg);
static void* manager(void *arg);
void threadExit();
TaskQueue<T>* m_taskQ;
pthread_t managerID;
pthread_t *threadIDs;
int minNum;
int maxNum;
int liveNum;
int busyNum;
int exitNum;
pthread_mutex_t mutexPool;
pthread_cond_t notempty;
bool shutdown;
};
#include "ThreadPool.h"
#include <iostream>
#include<string.h>
#include<string>
#include <unistd.h>
#include<pthread.h>
using namespace std;
template<typename T>
ThreadPool<T>::ThreadPool(int min,int max){
m_taskQ=new TaskQueue<T>;
do{
if(m_taskQ==nullptr){
cout<<"malloc taskQ fail..."<<endl;
return;
}
threadIDs=new pthread_t[max];
if(threadIDs==nullptr){
cout<<"malloc threadIDs fail..."<<endl;
return;
}
if (pthread_mutex_init(&mutexPool, NULL) != 0 ||
pthread_cond_init(¬empty, NULL) != 0)
{
cout << "init mutex or condition fail..." << endl;
break;
}
memset(threadIDs,0,sizeof(pthread_t)*max);
minNum=min;
maxNum=max;
busyNum=0;
liveNum=min;
exitNum=0;
shutdown=false;
pthread_create(&managerID,NULL,manager,this);
for(int i=0;i<min;++i){
pthread_create(&threadIDs[i],NULL,worker,this);
}
}while(0);
}
template<typename T>
ThreadPool<T>::~ThreadPool(){
shutdown=true;
pthread_join(managerID,NULL);
for(int i=0;i<liveNum;i++)
pthread_cond_signal(¬empty);
if(m_taskQ) delete m_taskQ;
if(threadIDs) delete[]threadIDs;
pthread_mutex_destroy(&mutexPool);
pthread_cond_destroy(¬empty);
}
template<typename T>
void ThreadPool<T>::addTask(Task<T> task){
if(shutdown) return;
m_taskQ->addTask(task);
pthread_cond_signal(¬empty);
}
template<typename T>
int ThreadPool<T>::getliveNum(){
int threadNum=0;
pthread_mutex_lock(&mutexPool);
threadNum=liveNum;
pthread_mutex_unlock(&mutexPool);
return threadNum;
}
template<typename T>
int ThreadPool<T>::getbusyNum(){
int busyNum=0;
pthread_mutex_lock(&mutexPool);
busyNum=busyNum;
pthread_mutex_unlock(&mutexPool);
return busyNum;
}
template<typename T>
void* ThreadPool<T>::worker(void* arg){
ThreadPool *pool=static_cast<ThreadPool*>(arg);
while(true){
pthread_mutex_lock(&pool->mutexPool);
while(pool->m_taskQ->taskNumber()==0&&!pool->shutdown){
pthread_cond_wait(&pool->notempty,&pool->mutexPool);
if(pool->exitNum>0){
pool->exitNum--;
if(pool->liveNum>pool->minNum){
pool->liveNum--;
pthread_mutex_unlock(&pool->mutexPool);
pool->threadExit();
}
}
}
if(pool->shutdown){
pthread_mutex_unlock(&pool->mutexPool);
pool->threadExit();
}
Task<T> task=pool->m_taskQ->takeTask();
pool->busyNum++;
pthread_mutex_unlock(&pool->mutexPool);
cout << "thread " << to_string(pthread_self()) << " start working..." << endl;
task.function(task.arg);
delete task.arg;
task.arg = nullptr;
cout << "thread " << to_string(pthread_self()) << " end working..."<<endl;
pthread_mutex_lock(&pool->mutexPool);
pool->busyNum--;
pthread_mutex_unlock(&pool->mutexPool);
}
return nullptr;
}
template<typename T>
void* ThreadPool<T>::manager(void* arg){
ThreadPool* pool=static_cast<ThreadPool*>(arg);
while(!pool->shutdown){
sleep(5);
pthread_mutex_lock(&pool->mutexPool);
int queuesize=pool->m_taskQ->taskNumber();
int liveNum=pool->liveNum;
int busyNum=pool->busyNum;
pthread_mutex_unlock(&pool->mutexPool);
const int number=2;
if(queuesize>liveNum-busyNum&&liveNum<pool->maxNum){
pthread_mutex_lock(&pool->mutexPool);
int num=0;
for(int i=0;i<pool->maxNum&&num<number&&pool->liveNum<pool->maxNum;i++)
{
if(pool->threadIDs[i]==0){
pthread_create(&pool->threadIDs[i],NULL,worker,pool);
num++;
pool->liveNum++;
}
}
pthread_mutex_unlock(&pool->mutexPool);
}
if(busyNum*2<liveNum&&liveNum>pool->minNum){
pthread_mutex_lock(&pool->mutexPool);
pool->exitNum=number;
pthread_mutex_unlock(&pool->mutexPool);
for(int i=0;i<number;i++)
pthread_cond_signal(&pool->notempty);
}
}
return nullptr;
}
template<typename T>
void ThreadPool<T>::threadExit(){
pthread_t tid=pthread_self();
for(int i=0;i<maxNum;i++)
{
if(threadIDs[i]==tid){
cout<<"threadExit() function:called"<<
to_string(pthread_self())<<"exiting ..."<<endl;
threadIDs[i]=0;
break;
}
}
pthread_exit(NULL);
}