/*
* threadpool.h
*
* Created on: 2016年5月11日
* Author: qiangqaz
*/
#ifndef THREADPOOL_H_
#define THREADPOOL_H_
#include <pthread.h>
typedef void (*CB_FUN)(void *);
//task structure
typedef struct task
{
void *argv; //task handler's arg
CB_FUN handler; //task handler
struct task *next; //task quene pointer
}threadpool_task_t;
//task queue
typedef struct task_queue
{
threadpool_task_t *head;
threadpool_task_t **tail;
unsigned int cur_task_num;
}threadpool_task_queue_t;
//thread pool
typedef struct threadpool
{
pthread_mutex_t mutex;
pthread_cond_t cond;
threadpool_task_queue_t tasks;
unsigned int thread_num;
}threadpool_t;
//thread pool configuration
typedef struct threadpool_conf
{
unsigned int thread_num;
}threadpool_conf_t;
threadpool_t *threadpool_init(threadpool_conf_t *conf);
int threadpool_add_task(threadpool_t *pool, CB_FUN handler, void *argv);
void threadpool_destroy(threadpool_t *pool);
#endif /* THREADPOOL_H_ */
<pre name="code" class="cpp">/*
* threadpool.c
*
* Created on: 2016年5月11日
* Author: qiangqaz
*/
#include "threadpool.h"
static pthread_key_t key;
inline int threadpool_key_create()
{
return pthread_key_create(&key, NULL);
}
inline void threadpool_key_destroy()
{
pthread_key_delete(key);
}
int thread_conf_check(threadpool_conf_t *conf)
{
if (NULL == conf)
{
printf("conf null\n");
return -1;
}
if (conf->thread_num < 1)
{
printf("conf < 1\n");
return -1;
}
return conf->thread_num;
}
void threadpool_task_queue_init(threadpool_task_queue_t *task_queue)
{
task_queue->head = NULL;
task_queue->tail = &task_queue->head;
}
int threadpool_mutex_create(pthread_mutex_t *mutex)
{
int ret = 0;
pthread_mutexattr_t attr;
if (0 != pthread_mutexattr_init(&attr))
{
return -1;
}
if (0 != pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
{
pthread_mutexattr_destroy(&attr);
}
ret = pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
return ret;
}
void threadpool_mutex_destroy(pthread_mutex_t *mutex)
{
pthread_mutex_destroy(mutex);
}
int threadpool_cond_create(pthread_cond_t *cond)
{
return pthread_cond_init(cond, NULL);
}
void threadpool_cond_destroy(pthread_cond_t *cond)
{
pthread_cond_destroy(cond);
}
void threadpool_cycle(void *argv)
{
unsigned int exit_flag = 0;
sigset_t set;
threadpool_task_t *ptask = NULL;
threadpool_t *pool = (threadpool_t*)argv;
//只注册以下致命信号,其他全部屏蔽
sigfillset(&set);
sigdelset(&set, SIGILL);
sigdelset(&set, SIGFPE);
sigdelset(&set, SIGSEGV);
sigdelset(&set, SIGBUS);
if (pthread_setspecific(key,(void*)&exit_flag) != 0){//设置exit_flag = 0
return;
}
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0){
return;
}
while(!exit_flag){ //exit_flag为1时线程退出
if (pthread_mutex_lock(&pool->mutex) != 0){ //加锁
return;
}
while(pool->tasks.head == NULL){
if (pthread_cond_wait(&pool->cond, &pool->mutex) != 0){
pthread_mutex_unlock(&pool->mutex);
return;
}
}
ptask = pool->tasks.head; //从任务队列中获取一个任务任务节点
pool->tasks.head = ptask->next;
pool->tasks.cur_task_num--; //当前任务数--
if (pool->tasks.head == NULL){
pool->tasks.tail = &pool->tasks.head;
}
if (pthread_mutex_unlock(&pool->mutex) != 0){ //解锁
return;
}
ptask->handler(ptask->argv); //执行任务。
free(ptask);
ptask = NULL;
}
pthread_exit(0);
}
int threadpool_create(threadpool_t *pool)
{
pthread_t pid;
pthread_attr_t attr;
int i = 0;
if (0 != pthread_attr_init(&attr))
{
return -1;
}
for (i = 0; i < pool->thread_num; i++)
{
pthread_create(&pid, &attr, threadpool_cycle, pool);
}
pthread_attr_destroy(&attr);
return 0;
}
threadpool_t *threadpool_init(threadpool_conf_t *conf)
{
threadpool_t *pool = NULL;
do
{
if (thread_conf_check(conf) == -1)
{
printf("invalid thread conf!\n");
break;
}
pool = (threadpool_t *)malloc(sizeof(threadpool_t));
if (NULL == pool)
{
printf("thread pool malloc failed.\n");
break;
}
pool->thread_num = conf->thread_num;
pool->tasks.cur_task_num = 0;
threadpool_task_queue_init(&pool->tasks);
if (0 != threadpool_key_create())
{
printf("thread pool key create failed.\n");
free(pool);
break;
}
if (0 != threadpool_mutex_create(&pool->mutex))
{
printf("thread mutex create failed.\n");
threadpool_key_destroy();
free(pool);
break;
}
if (0 != threadpool_cond_create(&pool->cond))
{
printf("thread cond create failed.\n");
threadpool_key_destroy();
threadpool_mutex_destroy(&pool->mutex);
free(pool);
break;
}
if (0 != threadpool_create(pool))
{
printf("thread pool create failed.\n");
threadpool_key_destroy();
threadpool_mutex_destroy(&pool->mutex);
threadpool_cond_destroy(&pool->cond);
free(pool);
break;
}
return pool;
}while (0);
return NULL;
}
//向线程池中添加一个任务。handler为回掉函数,argv为参数
int threadpool_add_task(threadpool_t *pool, CB_FUN handler, void* argv)
{
threadpool_task_t *task = NULL;
int ret = 0;
//申请一个任务节点并赋值
task = (threadpool_task_t *)malloc(sizeof(threadpool_task_t));
if (task == NULL)
{
printf("task null\n");
return -1;
}
task->handler = handler;
task->argv = argv;
task->next = NULL;
if ((ret = pthread_mutex_lock(&pool->mutex)) != 0)
{
printf("mutex lock failed. ret = %d\n",ret);
//加锁
free(task);
return -1;
}
do
{
//将任务节点尾插到任务队列
*(pool->tasks.tail) = task;
pool->tasks.tail = &task->next;
pool->tasks.cur_task_num++;
//通知阻塞的线程
if (pthread_cond_signal(&pool->cond) != 0){
break;
}
//解锁
pthread_mutex_unlock(&pool->mutex);
return 0;
}while(0);
pthread_mutex_unlock(&pool->mutex);
free(task);
return -1;
}
//线程池退出函数
void threadpool_exit_cb(void* argv)
{
unsigned int *lock = argv;
unsigned int *pexit_flag = NULL;
pexit_flag = (int *)pthread_getspecific(key);
*pexit_flag = 1; //将exit_flag置1
pthread_setspecific(key, (void*)pexit_flag);
*lock = 0;
}
//销毁线程池。
void threadpool_destroy(threadpool_t *pool)
{
unsigned int n = 0;
volatile unsigned int lock;
//z_threadpool_exit_cb函数会使对应线程退出
for (; n < pool->thread_num; n++)
{
lock = 1;
if (threadpool_add_task(pool, threadpool_exit_cb, &lock) != 0)
{
return;
}
while (lock)
{
usleep(1);
}
}
threadpool_mutex_destroy(&pool->mutex);
threadpool_cond_destroy(&pool->cond);
threadpool_key_destroy();
free(pool);
}
/*
* main.c
*
* Created on: 2016年5月11日
* Author: qiangqaz
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "threadpool.h"
int testfun(void *argv)
{
int *num = (int*)argv;
printf("testfun thread_id = %u num = %d\n",pthread_self(),*num);
//sleep(3);
return 0;
}
int main(int argc, char **argv)
{
int array[10] = {0};
int i = 0;
threadpool_conf_t conf; //实例化启动参数
conf.thread_num = 5;
threadpool_t *pool = threadpool_init(&conf);//初始化线程池
if (pool == NULL)
{
return 0;
}
for (; i < 10; i++){
array[i] = i;
while(1)
{
if (threadpool_add_task(pool, testfun, &array[i]) == 0)
{
break;
}
printf("error in i = %d\n",i);
break;
}
}
threadpool_destroy(pool);
return 0;
}