源码
debug.h
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
#define DEBUG_MSG(msg) { \
fprintf(stdout,"[file:%s,function:%s,line:%d],%s\n",__FILE__,__FUNCTION__,__LINE__,msg); \
fflush(stdout); \
}
#endif
thread_pool.h
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#define THREAD_POOL_TASK_NUM_MAX 256
#define THREAD_POOL_THREAD_NUM_MAX 8
#include <pthread.h>
typedef pthread_t thread_pool_thread_id_t;
typedef pthread_mutex_t thread_pool_mutex_t;
typedef pthread_cond_t thread_pool_cond_t;
typedef enum
{
STOPPED = 0,
SUSPEND = 1,
RUNNING = 2,
}thread_pool_status_t;
typedef struct
{
void *(*function)(void *arg);
void *arg;
}thread_pool_task_t;
typedef struct
{
thread_pool_status_t status;
thread_pool_mutex_t mutex;
thread_pool_cond_t cond;
void *(*threadCommonFun)(void *arg);
thread_pool_thread_id_t *threadIdArray;
thread_pool_task_t *taskArray;
int taskNum;
int taskIndex;
}thread_pool_t;
typedef enum
{
ERR_NONE = 0,
ERR_ARG_INVALID = 1,
ERR_TASK_FULL = 2,
ERR_FUNCTION_CALL = 3,
}thread_pool_error_t;
thread_pool_t *CreatThreadPool(void);
thread_pool_error_t InitThreadPool(thread_pool_t *pThreadPool);
thread_pool_error_t ThreadPoolAddTask(thread_pool_t *pThreadPool,thread_pool_task_t *pTask);
thread_pool_error_t ThreadPoolDestroy(thread_pool_t *pThreadPool);
void *threadCommonFunction(void *arg);
#endif
thread_pool.c
#include <stdio.h>
#include <stdlib.h>
#include "thread_pool.h"
#include "debug.h"
thread_pool_t *CreatThreadPool(void)
{
thread_pool_t *pThreadPool;
pThreadPool = (thread_pool_t *)malloc(sizeof(thread_pool_t));
if (pThreadPool == NULL)
{
DEBUG_MSG("malloc error");
return(NULL);
}
return(pThreadPool);
}
thread_pool_error_t InitThreadPool(thread_pool_t *pThreadPool)
{
if (pThreadPool == NULL)
{
DEBUG_MSG("pThreadPool NULL");
return(ERR_ARG_INVALID);
}
pThreadPool->status = SUSPEND;
int intRet = -1;
intRet = pthread_mutex_init(&pThreadPool->mutex,NULL);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_init error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
intRet = pthread_cond_init(&pThreadPool->cond,NULL);
if (intRet != 0)
{
DEBUG_MSG("pthread_cond_init error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
pThreadPool->threadCommonFun = threadCommonFunction;
thread_pool_thread_id_t *pThreadPoolThreadID;
pThreadPoolThreadID = (thread_pool_thread_id_t*)malloc(sizeof(thread_pool_thread_id_t) * THREAD_POOL_THREAD_NUM_MAX);
if (pThreadPoolThreadID == NULL)
{
DEBUG_MSG("malloc error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
pThreadPool->threadIdArray = pThreadPoolThreadID;
intRet = pthread_mutex_lock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_lock error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
for (int i = 0; i < THREAD_POOL_THREAD_NUM_MAX; i ++)
{
intRet = pthread_create(&pThreadPool->threadIdArray[i],NULL,pThreadPool->threadCommonFun,pThreadPool);
if (intRet != 0)
{
DEBUG_MSG("malloc error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
}
intRet = pthread_mutex_unlock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_unlock error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
thread_pool_task_t *pThreadPoolTask;
pThreadPoolTask = (thread_pool_task_t*)malloc(sizeof(thread_pool_task_t) * THREAD_POOL_THREAD_NUM_MAX);
if (pThreadPoolTask == NULL)
{
DEBUG_MSG("malloc error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
pThreadPool->taskArray = pThreadPoolTask;
pThreadPool->taskNum = 0;
pThreadPool->taskIndex = 0;
return(ERR_NONE);
}
thread_pool_error_t ThreadPoolAddTask(thread_pool_t *pThreadPool,thread_pool_task_t *pTask)
{
if (pThreadPool == NULL)
{
DEBUG_MSG("pThreadPool NULL");
return(ERR_ARG_INVALID);
}
if (pTask == NULL)
{
DEBUG_MSG("pTask NULL");
return(ERR_ARG_INVALID);
}
if (pThreadPool->taskNum >= THREAD_POOL_TASK_NUM_MAX)
{
DEBUG_MSG("pTask NULL");
return(ERR_TASK_FULL);
}
pThreadPool->status = SUSPEND;
pThreadPool->taskArray[pThreadPool->taskNum].function = pTask->function;
pThreadPool->taskArray[pThreadPool->taskNum].arg = pTask->arg;
pThreadPool->taskNum ++;
pThreadPool->status = RUNNING;
int intRet = -1;
intRet = pthread_cond_signal(&pThreadPool->cond);
if (intRet != 0)
{
DEBUG_MSG("pthread_cond_signal error");
(void)ThreadPoolDestroy(pThreadPool);
return(ERR_FUNCTION_CALL);
}
return(ERR_NONE);
}
thread_pool_error_t ThreadPoolDestroy(thread_pool_t *pThreadPool)
{
if (pThreadPool == NULL)
{
DEBUG_MSG("pThreadPool NULL");
return(ERR_ARG_INVALID);
}
pThreadPool->status = STOPPED;
int intRet = -1;
// 惊群
intRet = pthread_cond_broadcast(&pThreadPool->cond);
if (intRet != 0)
{
DEBUG_MSG("pthread_cond_broadcast error");
return(ERR_FUNCTION_CALL);
}
// 收尸
for (int i = 0; i < THREAD_POOL_THREAD_NUM_MAX; i ++)
{
intRet = pthread_join(pThreadPool->threadIdArray[i],NULL);
if (intRet != 0)
{
DEBUG_MSG("pthread_join error");
return(ERR_FUNCTION_CALL);
}
}
if (pThreadPool->threadIdArray != NULL)
{
free(pThreadPool->threadIdArray);
}
if (pThreadPool->taskArray != NULL)
{
free(pThreadPool->taskArray);
}
free(pThreadPool);
return(ERR_NONE);
}
void *threadCommonFunction(void *arg)
{
thread_pool_t *pThreadPool = (thread_pool_t *)arg;
thread_pool_task_t *pTask = NULL;
int intRet = -1;
for (;;)
{
// fprintf(stdout,"tid:%ld before pthread_mutex_lock\n",pthread_self());
intRet = pthread_mutex_lock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_lock error");
pthread_exit(NULL);
}
// fprintf(stdout,"tid:%ld after pthread_mutex_lock\n",pthread_self());
for (;;)
{
if (pThreadPool->status == STOPPED)
{
// fprintf(stdout,"tid:%ld located STOPPED\n",pthread_self());
intRet = pthread_mutex_unlock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_unlock error");
pthread_exit(NULL);
}
pthread_exit(NULL);
}
else if (pThreadPool->status == SUSPEND)
{
// fprintf(stdout,"tid:%ld located SUSPEND\n",pthread_self());
intRet = pthread_cond_wait(&pThreadPool->cond,&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_cond_wait error");
intRet = pthread_mutex_unlock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_unlock error");
pthread_exit(NULL);
}
pthread_exit(NULL);
}
// fprintf(stdout,"tid:%ld located SUSPEND && if taskNum\n",pthread_self());
if (pThreadPool->taskNum < 1)
{
continue;
}
else
{
// fprintf(stdout,"tid:%ld located SUSPEND && break\n",pthread_self());
break;
}
}
else if (pThreadPool->status == RUNNING)
{
// fprintf(stdout,"tid:%ld located RUNNING then break\n",pthread_self());
break;
}
}
if (pThreadPool->taskIndex == pThreadPool->taskNum)
{
pThreadPool->taskIndex = 0;
}
// fprintf(stdout,"tid:%ld before get task\n",pthread_self());
pTask = &pThreadPool->taskArray[pThreadPool->taskIndex];
// fprintf(stdout,"tid:%ld after get task\n",pthread_self());
pThreadPool->taskIndex ++;
// fprintf(stdout,"tid:%ld before pthread_mutex_unlock\n",pthread_self());
intRet = pthread_mutex_unlock(&pThreadPool->mutex);
if (intRet != 0)
{
DEBUG_MSG("pthread_mutex_unlock error");
pthread_exit(NULL);
}
// fprintf(stdout,"tid:%ld after pthread_mutex_unlock\n",pthread_self());
(pTask->function)(pTask->arg);
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "thread_pool.h"
#include "debug.h"
#define THREAD_MSG(msg) { fprintf(stdout,"tid:%ld in %s\n",pthread_self(),msg); }
void *task1(void *arg)
{
THREAD_MSG("task1");
}
void *task2(void *arg)
{
THREAD_MSG("task2");
}
void *task3(void *arg)
{
THREAD_MSG("task3");
}
void *task4(void *arg)
{
THREAD_MSG("task4");
}
void *task5(void *arg)
{
THREAD_MSG("task5");
}
void *task6(void *arg)
{
THREAD_MSG("task6");
}
void *task7(void *arg)
{
THREAD_MSG("task7");
}
void *task8(void *arg)
{
THREAD_MSG("task8");
}
int main(int argc,char **argv)
{
thread_pool_t *pool;
thread_pool_error_t ret;
pool = CreatThreadPool();
if (pool == NULL)
{
DEBUG_MSG("CreatThreadPool error");
exit(1);
}
ret = InitThreadPool(pool);
if (ret != ERR_NONE)
{
DEBUG_MSG("CreatThreadPool error");
exit(1);
}
thread_pool_task_t taskArr[8];
taskArr[0].function = task1;
taskArr[1].function = task2;
taskArr[2].function = task3;
taskArr[3].function = task4;
taskArr[4].function = task5;
taskArr[5].function = task6;
taskArr[6].function = task7;
taskArr[7].function = task8;
for (int i = 0; i < 8; i ++)
{
taskArr[i].arg = NULL;
}
for (int i = 0; i < 8; i ++)
{
ret = ThreadPoolAddTask(pool,&taskArr[i]);
if (ret != ERR_NONE)
{
DEBUG_MSG("ThreadPoolAddTask error");
exit(1);
}
}
for (;;)
{
;
}
exit(0);
}