网上看得代码,两个小时时间改进一下源代码,增加log机制:http://blog.youkuaiyun.com/zzran/article/details/42779851
#ifndef __thread_pool_h__
#define __thread_pool_h__
#include <pthread.h>
typedef struct work_s {
void* (*routine)(void*);
void* args;
struct work_s* next;
}work_t;
typedef struct thread_pool_s {
int shutdown;
int max_thr_num;
work_t* queue_head;
pthread_t* thr_ids;
pthread_mutex_t mutex;
pthread_cond_t cond;
}thread_pool_t;
int thread_pool_init(int max_thr_num);
void thread_pool_destroy();
int thread_pool_add(void*(*routine)(void*), void* args);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "log.h"
#include "thread_pool.h"
static thread_pool_t* tpool;
static void* thread_routine(void* args);
int thread_pool_init(int max_thr_num) {
int i;
int cond_inited = 0;
int mutex_inited = 0;
if (0 >= max_thr_num) {
TRACE_ERROR("thread_pool_init(): max_thr_num <= 0.");
return -1;
}
tpool = (thread_pool_t*)calloc(1, sizeof(thread_pool_t));
if (NULL == tpool)
goto err;
tpool->shutdown = 0;
tpool->max_thr_num = max_thr_num;
tpool->queue_head = NULL;
if (0 != pthread_mutex_init(&tpool->mutex, NULL)) {
TRACE_ERROR("thread_pool_init(): init mutext, errno: %d, error:%s", errno, strerror(errno));
goto err;
} else {
mutex_inited = 1;
}
if (0 != pthread_cond_init(&tpool->cond, NULL)) {
TRACE_ERROR("thread_pool_init(): init cond, errno: %d, error:%s", errno, strerror(errno));
goto err;
} else {
cond_inited = 1;
}
tpool->thr_ids = (pthread_t*)calloc(max_thr_num, sizeof(pthread_t));
if (NULL == tpool->thr_ids) {
TRACE_ERROR("thread_pool_init(): create threads error.");
goto err;
}
for (i = 0; i < max_thr_num; i++) {
if (0 != pthread_create(&tpool->thr_ids[i], NULL, thread_routine, NULL)) {
TRACE_ERROR("thread_pool_init(): create thread %d error.", i);
goto err;
}
}
goto end;
err:
if (tpool) {
if (mutex_inited)
pthread_mutex_destroy(&tpool->mutex);
if (cond_inited)
pthread_cond_destroy(&tpool->cond);
if (NULL != tpool->thr_ids) {
free(tpool->thr_ids);
}
free(tpool);
}
end:
TRACE_DEBUG("thread_pool_init(): init pool successful.");
return 0;
}
static void* thread_routine(void* arg) {
work_t* work = NULL;
while (1) {
pthread_mutex_lock(&tpool->mutex);
while (!tpool->shutdown && NULL == tpool->queue_head) {
pthread_cond_wait(&tpool->cond, &tpool->mutex);
}
if (tpool->shutdown) {
TRACE_DEBUG("thread_routine():thread pool shutdown.");
pthread_mutex_unlock(&tpool->mutex);
pthread_exit(NULL);
}
work = tpool->queue_head;
tpool->queue_head = tpool->queue_head->next;
pthread_mutex_unlock(&tpool->mutex);
work->routine(work->args);
free(work);
}
return NULL;
}
void thread_pool_destroy() {
int i;
work_t* work = NULL;
if (tpool->shutdown) {
TRACE_DEBUG("thread_pool_destroy(): already shutdown.");
return;
}
tpool->shutdown = 1;
pthread_mutex_lock(&tpool->mutex);
pthread_cond_broadcast(&tpool->cond);
pthread_mutex_unlock(&tpool->mutex);
for (i = 0; i < tpool->max_thr_num; i++) {
TRACE_DEBUG("thread_pool_destroy(): thread %d finish.", i);
pthread_join(tpool->thr_ids[i], NULL);
}
free(tpool->thr_ids);
while (tpool->queue_head) {
work = tpool->queue_head;
tpool->queue_head = tpool->queue_head->next;
free(work);
}
pthread_mutex_destroy(&tpool->mutex);
pthread_cond_destroy(&tpool->cond);
free(tpool);
tpool = NULL;
}
int thread_pool_add(void*(*routine)(void*), void* args) {
work_t* work, *node;
if (NULL == routine) {
TRACE_ERROR("thread_pool_add(): no routine.");
return 0;
}
work = (work_t*)calloc(1, sizeof(work_t));
if (NULL == work) {
TRACE_ERROR("thread_pool_add(): calloc failed.");
return 0;
}
work->routine = routine;
work->args = args;
pthread_mutex_lock(&tpool->mutex);
if (NULL == tpool->queue_head) {
tpool->queue_head = work;
} else {
node = tpool->queue_head;
while (node->next) {
node = node->next;
}
node->next = work;
}
pthread_cond_signal(&tpool->cond);
pthread_mutex_unlock(&tpool->mutex);
return 0;
}
测试代码:
#include <stdio.h>
#include <unistd.h>
#include "log.h"
#include "thread_pool.h"
void *func(void *arg) {
TRACE_INFO("thread %d working", (int)arg);
return NULL;
}
int main(int argc, char* argv[]) {
set_log_path("/Users/zzran/c-program/thread_test/l");
TRACE_DEBUG("main():");
if (0 != thread_pool_init(5)) {
TRACE_ERROR("main(): thread pool init failed.");
return 0;
}
int i;
for (i = 0; i < 10; ++i) {
thread_pool_add(func, (void*)i);
}
sleep(2);
thread_pool_destroy();
return 0;
}