#ifndef THREAD_POOL_VITO_H
#define THREAD_POOL_VITO_H
#ifdef _WIN32
#include<windows.h>
#include<process.h>
#else
#include <pthread.h>
#endif
#define LL_ADD(item, list) do { \
item->prev = NULL; \
item->next = list; \
if(list!= NULL) list->prev = item; \
list = item; \
} while(0)
#define LL_REMOVE(item, list) do { \
if (item->prev != NULL) item->prev->next = item->next; \
if (item->next != NULL) item->next->prev = item->prev; \
if (list == item) list = item->next; \
item->prev = item->next = NULL; \
} while(0)
class ThreadPoolVito;
//工作线程
class WorkThread
{
public:
#ifdef _WIN32
HANDLE _handle;
DWORD _id;
#else
pthread_t thread;
#endif
int terminate;
ThreadPoolVito *pWorkPool;
WorkThread *prev;
WorkThread *next;
};
//任务
class Task
{
public:
#ifdef _WIN32
unsigned(__stdcall* task_fun)(Task *task);
#else
void(*task_fun)(Task *task);
#endif
void *user_data;
Task *prev;
Task *next;
};
class ThreadPoolVito
{
public:
ThreadPoolVito(int numThread=1);
~ThreadPoolVito();
void addTaskToQueue(Task *pTask);
void threadPoolShutdown();
#ifdef _WIN32
static unsigned int __stdcall workerThread(void* ptr);
#else
static void * workerThread(void* ptr);
#endif
public:
WorkThread *pWorker;
Task *pTask;
#ifdef _WIN32
mutable CRITICAL_SECTION taskMutex;
mutable CONDITION_VARIABLE taskCond;
#else
pthread_mutex_t taskMutex;
pthread_cond_t taskCond;
#endif
};
#endif
#include "ThreadPoolVito.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
unsigned int __stdcall ThreadPoolVito::workerThread(void* ptr)
{
WorkThread *pWorker = (WorkThread*)ptr;
while (true)
{
EnterCriticalSection(&pWorker->pWorkPool->taskMutex);
while (pWorker->pWorkPool->pTask == NULL)
{
if (pWorker->terminate)
{
break;
}
SleepConditionVariableCS(&pWorker->pWorkPool->taskCond, &pWorker->pWorkPool->taskMutex, INFINITE);
}
if (pWorker->terminate)
{
LeaveCriticalSection(&pWorker->pWorkPool->taskMutex);
break;
}
Task *pTask = pWorker->pWorkPool->pTask;
if (pTask != NULL)
{
LL_REMOVE(pTask, pWorker->pWorkPool->pTask);
}
LeaveCriticalSection(&pWorker->pWorkPool->taskMutex);
if (NULL == pTask)
{
continue;
}
pTask->task_fun(pTask);
}
free(pWorker);
ExitThread(pWorker->_id);
}
#else
void * ThreadPoolVito::workerThread(void* ptr)
{
WorkThread *pWorker = (WorkThread*)ptr;
while (true)
{
pthread_mutex_lock(&pWorker->pWorkPool->taskMutex);
while (pWorker->pWorkPool->pTask == NULL)
{
if (pWorker->terminate)
{
break;
}
pthread_cond_wait(&pWorker->pWorkPool->taskCond, &pWorker->pWorkPool->taskMutex);
}
if (pWorker->terminate)
{
pthread_mutex_unlock(&pWorker->pWorkPool->taskMutex);
break;
}
Task *pTask = pWorker->pWorkPool->pTask;
if (pTask != NULL)
{
LL_REMOVE(pTask, pWorker->pWorkPool->pTask);
}
pthread_mutex_unlock(&pWorker->pWorkPool->taskMutex);
if (NULL == pTask)
{
continue;
}
pTask->task_fun(pTask);
}
free(pWorker);
pthread_exit(NULL);
}
#endif
ThreadPoolVito::ThreadPoolVito(int numThread)
{
if (numThread < 1)
numThread = 1;
this->pTask = NULL;
this->pWorker = NULL;
#ifdef _WIN32
InitializeCriticalSection(&this->taskMutex);
InitializeConditionVariable(&this->taskCond);
int i = 0;
for (i = 0; i < numThread; i++)
{
WorkThread *pWorker = (WorkThread*)malloc(sizeof(WorkThread));
if (pWorker == NULL) {
perror("malloc");
}
memset(pWorker, 0, sizeof(WorkThread));
pWorker->pWorkPool = this;
unsigned int id;
pWorker->_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, workerThread, (void*)pWorker, 0, &id));
pWorker->_id = id;
if (pWorker->_handle == NULL)
{
perror("pthread_create");
free(pWorker);
}
LL_ADD(pWorker, this->pWorker);
}
#else
pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
memcpy(&this->taskCond, &blank_cond, sizeof(this->taskCond));
pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
memcpy(&this->taskMutex, &blank_mutex, sizeof(this->taskMutex));
int i = 0;
for (i = 0; i < numThread; i++)
{
WorkThread *pWorker = (WorkThread*)malloc(sizeof(WorkThread));
if (pWorker == NULL) {
perror("malloc");
}
memset(pWorker, 0, sizeof(WorkThread));
pWorker->pWorkPool = this;
int ret = pthread_create(&pWorker->thread, NULL, workerThread, (void *)pWorker);
if (ret)
{
perror("pthread_create");
free(pWorker);
}
LL_ADD(pWorker, this->pWorker);
}
#endif
}
ThreadPoolVito::~ThreadPoolVito()
{
}
void ThreadPoolVito::addTaskToQueue(Task *pTask)
{
#ifdef _WIN32
EnterCriticalSection(&this->taskMutex);
LL_ADD(pTask, this->pTask);
WakeConditionVariable(&this->taskCond);
LeaveCriticalSection(&this->taskMutex);
#else
pthread_mutex_lock(&this->taskMutex);
LL_ADD(pTask, this->pTask);
pthread_cond_signal(&this->taskCond);
pthread_mutex_unlock(&this->taskMutex);
#endif
}
void ThreadPoolVito::threadPoolShutdown()
{
WorkThread *pWorker = NULL;
for (pWorker = this->pWorker; pWorker != NULL; pWorker = pWorker->next)
{
pWorker->terminate = 1;
}
#ifdef _WIN32
EnterCriticalSection(&this->taskMutex);
this->pWorker = NULL;
this->pTask = NULL;
WakeAllConditionVariable(&this->taskCond);
LeaveCriticalSection(&this->taskMutex);
#else
pthread_mutex_lock(&this->taskMutex);
this->pWorker = NULL;
this->pTask = NULL;
pthread_cond_broadcast(&this->taskCond);
pthread_mutex_unlock(&this->taskMutex);
#endif
}
//#include "MutexVito.h"
//#include "ThreadVito.h"
//#include "CondVito.h"
#include "ThreadPoolVito.h"
#include<iostream>
#include<thread>
#include<stdio.h>
#include<stdlib.h>
#ifdef _WIN32
#include<windows.h>
#include<process.h>
#else
#include <pthread.h>
#include <unistd.h>
#endif
#define VITO_MAX_THREAD 30
#define VITO_COUNTER_SIZE 300
#ifdef _WIN32
unsigned int __stdcall vito_counter(Task *pTask)
#else
void vito_counter(Task *pTask)
#endif
{
int index = *(int*)pTask->user_data;
//printf("index : %d, selfid : %lu\n", index, GetCurrentThreadId());
printf("index : %d, selfid : %lu\n", index, pthread_self());
free(pTask->user_data);
free(pTask);
//return 0;
}
void test_threadPool()
{
/*ThreadPoolStruct pool;
threadPoolInit(&pool, VITO_MAX_THREAD);
int i = 0;
for (i = 0; i < VITO_COUNTER_SIZE; i++)
{
nTask *pTask = (nTask*)malloc(sizeof(nTask));
if (pTask == NULL)
{
perror("malloc");
}
pTask->task_fun = vito_counter;
pTask->user_data = malloc(sizeof(int));
*(int*)pTask->user_data = i;
addTaskToQueue(&pool, pTask);
}*/
ThreadPoolVito pool(VITO_MAX_THREAD);
for (int i = 0; i < VITO_COUNTER_SIZE; i++)
{
Task *pTask = (Task*)malloc(sizeof(Task));
if (pTask == NULL)
{
perror("malloc");
}
pTask->task_fun = vito_counter;
pTask->user_data = malloc(sizeof(int));
*(int*)pTask->user_data = i;
pool.addTaskToQueue(pTask);
}
while (true)
{
sleep(2);
}
}
int main()
{
test_threadPool();
return 0;
}