最近做的一些工作需要用到线程池技术,因此参考了一些资料和书籍,如《0bug c/c++商用工程之道》。
为此在linux平台上用纯c写了一个线程池的实现。
在此列出了原代码。
主要用到的数据结构有
1.struct thread_pool_t // thread pool 的实现代码
2.struct thread_pool_token_t //在thread pool 中用到的结构,一个该类型变量代表一条线程
3.struct thread_pool_job_t //当线前程处理该任务将回调结构
设计思路:
主线程创建线程池的控制线程,
管理线程将进入循环来做以下事情:
1.如果当前空闲进程不足并且总线程数没有达到上限,将创建一条空闲线程,至道空闲线程达到3条(见THREAD_POOL_MIN_IDLE_SIZE)
2.不断检查工作任务队列,有则安排一条空闲线程对该任务进行处理
普通线程被管理线程创建后也将进入循环来做以下事情:
1.检查当前assign的thread_pool_token_t结构的状态,如果是TREAD_POOL_STATE_BUSY则调用thread_pool_token_t所注册的回调函数来处理任务。
2.完成该任务后检测当前空闲进程够不够,如果太多则退出本线程,否则会改写运行状态为TREAD_POOL_STATE_IDLE后继续循环
注册任务:
1.当没有空闲线程可用时将把该任务加入工作任务队列(需定义_THREAD_POOL_JOB_LIST_),以备将来有空闲线程是能够进行处理。
主要文件 :
1.thread_pool.h
#ifndef _LIB_DOL_THREAD_POOL_H_
#define _LIB_DOL_THREAD_POOL_H_
#include "thread_pool.def"
#include <pthread.h>
#define THREAD_POOL_MIN_SIZE 5 /* at least 5 threads, 4 job + 1 manage thread */
#define THREAD_POOL_MIN_IDLE_SIZE 3 /* at least 3 threads idle to improve the efficiency */
#define THREAD_POOL_DEFAULT_SIZE 10 /* default threads in thread pool */
#define THREAD_POOL_MAX_SIZE 100 /* max threads in thread pool */
#define TREAD_POOL_STATE_NOTRUN 0
#define TREAD_POOL_STATE_IDLE 1
#define TREAD_POOL_STATE_BUSY 2
#define TREAD_POOL_REG_OK 0
#define TREAD_POOL_REG_ERR -1
#define TREAD_POOL_REG_ERR_FULL -2
#define ETPNOUSE -2 /* thread pool can not use */
#define ETPERR -1 /* thread pool over flow */
#define ETPOK 0 /* thread pool register ok */
#define CREATE_THREAD_SLEEP ( 200 * 1000 ) //200ms
#define LOOP_SLEEP ( 150 * 1000 ) //150ms
typedef void (*job_call_back_t)(void * );
typedef struct _thread_pool_job{
/* call back function which the thread will call to process this job */
job_call_back_t call_back;
/* parameter for call back function */
void * param;
/* job desc */
char desc[64];
#ifdef _THREAD_POOL_JOB_LIST_
/* if too many job then we will use this list to store the other job */
struct _thread_pool_job* next;
#endif
}thread_pool_job_t;
struct _thread_pool;
typedef struct _thread_pool_token{
int token_id;
int state;
int total_job; /* total jobs */
pthread_t thread_id;
thread_pool_job_t* job;
struct _thread_pool* pool;
pthread_mutex_t lock;
} thread_pool_token_t;
typedef struct _thread_pool{
int size; /* thread pool size */
int active; /* total create thread count */
int busy; /* total busy thread count */
int idle; /* total idle thread count */
int quit; /* should we quit the thread 1-quit, 0-loop */
int total_job; /* total process register job */
int reg_err; /* total register err */
#ifdef _THREAD_POOL_JOB_LIST_
/* use a link list to buff job if too many jobs are registered */
thread_pool_job_t* job_head;
/* lock for manuplate job list */
pthread_mutex_t job_lock;
#endif
/* lock */
pthread_mutex_t pool_lock;
/* thread pool core data */
thread_pool_token_t token[THREAD_POOL_MAX_SIZE];
}thread_pool_t;
/*
* init a thread pool with pool_size threads
* if pool_size is 0 or less than THREAD_POOL_IDLE_SIZE then pool_size set to THREAD_POOL_DEFAULT_SIZE
* if pool_size is larger than THREAD_POOL_MAX_SIZE then pool_size set to THREAD_POOL_MAX_SIZE
* return 0 if ok, -1 if error
*/
int thread_pool_init(thread_pool_t * pool, int pool_size);
/*
* thread pool destroy
*/
void thread_pool_destroy(thread_pool_t * pool);
/*
* pool - the thread pool
* call_back - call back function for thread token to call
* param - call back function parameter
* desc - tsk description
* it's thread safe when multi thread register thread pool job
*/
int thread_pool_register_job(thread_pool_t * pool, job_call_back_t call_back, void * param, char* desc);
/*
* out put the pool statistic data to stdout
*/
void thread_pool_statistic(thread_pool_t * pool);
/*
* out put the pool run time data to stdout
*/
void thread_pool_runtime(thread_pool_t * pool);
/*
* change the default log file to log_file
*/
void thread_pool_set_log(char* log_file);
/* thread pool token thread serve function */
static void * thread_pool_serve(void * arg);
/* thread pool control thread function */
static void * thread_pool_manage(void * arg);
/* destroy the mutex lock */
static void thread_pool_clean_up_lock(thread_pool_t * pool);
/* thread pool log */
static void thread_pool_log(char* fmt, ...);
/*
* find a not use token
* -1 if not found , else the token index
*/
static int thread_pool_find_free_token(thread_pool_t * pool);
/*
* find a runing and idle token
* -1 if not found , else the token index
*/
static int thread_pool_find_serve_token(thread_pool_t * pool);
#ifdef _DEBUG_VERSION_
#define _DOL_FPRINTF_ fprintf
#else
#define _DOL_FPRINTF_ //fprintf
#endif
#ifdef _THREAD_POOL_JOB_LIST_
/* pop a job from job list */
static thread_pool_job_t* pop_job(thread_pool_t * pool);
/* push a job in job list */
static void push_job(thread_pool_t * pool, thread_pool_job_t* job);
/* destroy the job list */
static void destroy_job_list(thread_pool_job_t* job_head);
#endif
#endif // end if define _LIB_DOL_THREAD_POOL_H_
2. thread_pool.c
//COPYRIGHT AND PERMISSION NOTICE
//Copyright (c) 2010, Dolphin Cheung, <[email protected]>.
//All rights reserved.
//Permission to use, copy, modify, and distribute this software for any purpose
//with or without fee is hereby granted, provided that the above copyright
//notice and this permission notice appear in all copies.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
//NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
//OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
//OR OTHER DEALINGS IN THE SOFTWARE.
//Except as contained in this notice, the name of a copyright holder shall not
//be used in advertising or otherwise to promote the sale, use or other dealings
//in this Software without prior written authorization of the copyright holder.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>
#include "thread_pool.h"
static const char * default_log_file = "/var/log/libdol_tp.log";
static char real_log_file[256];
/* thread pool token thread serve function */
static void * thread_pool_serve(void * arg){
thread_pool_token_t* token = (thread_pool_token_t*) arg;
int self_quit = 0;
token->state = TREAD_POOL_STATE_IDLE;
pthread_mutex_lock(&(token->pool->pool_lock));
token->pool->idle ++;
token->pool->active++;
pthread_mutex_unlock(&(token->pool->pool_lock));
usleep(LOOP_SLEEP);
thread_pool_log("serve thread create: token:%d thread:%u pid:%d ppid:%d",token->token_id, token->thread_id,(int)getpid(),(int)getppid());
while(! token->pool->quit){
/* do we have job ? */
if(token->state == TREAD_POOL_STATE_BUSY
&& token->job && token->job->call_back){
/* modify pool stat. */
pthread_mutex_lock(&(token->pool->pool_lock));
token->pool->idle --;
token->pool->busy ++;
token->pool->total_job ++;
pthread_mutex_unlock(&(token->pool->pool_lock));
/*
* process this job; this job may be a daemon process
* so it may process all the time, you should design carefully
* when it's time to quit in the while loop for the daemon process
* the thread pool have no way to tell the daemon process we will quit
* so when quit the thread pool, you also need to tell your
* daemon process to quit.
*/
token->job->call_back(token->job->param);
pthread_mutex_lock(&(token->lock));
token->total_job ++;
free(token->job);
token->job = NULL;
token->state = TREAD_POOL_STATE_IDLE;
pthread_mutex_unlock(&(token->lock));
/* modify pool stat. */
pthread_mutex_lock(&(token->pool->pool_lock));
token->pool->idle ++;
token->pool->busy --;
/* too many idle thread ? */
if(token->pool->idle > THREAD_POOL_MIN_IDLE_SIZE){
self_quit = 1;
}
pthread_mutex_unlock(&(token->pool->pool_lock));
}
if(self_quit){
break;
}
usleep(LOOP_SLEEP);
}
thread_pool_log("serve thread quit: token:%d thread:%u job:%d pid:%d ppid:%d",
token->token_id, token->thread_id,token->total_job,(int)getpid(),(int)getppid());
//thread quit
pthread_mutex_lock(&(token->lock));
token->state = TREAD_POOL_STATE_NOTRUN;
token->thread_id = 0;
pthread_mutex_unlock(&(token->lock));
pthread_mutex_lock(&(token->pool->pool_lock));
token->pool->idle --;
token->pool->active --;
pthread_mutex_unlock(&(token->pool->pool_lock));
return NULL;
}
/* thread pool control thread function */
static void * thread_pool_manage(void * arg){
thread_pool_t *pool = (thread_pool_t*) arg;
thread_pool_job_t* job_node;
int i, rc , idle, active,busy;
if(pool == NULL){
thread_pool_log("WARNING: thread_pool_manage stop when pool is NULL");
return NULL;
}
pool->active++;
usleep(CREATE_THREAD_SLEEP );
thread_pool_log("manage thread create. pid:%d ppid:%d",(int)getpid(),(int)getppid());
while(! pool->quit){
pthread_mutex_lock(&(pool->pool_lock));
idle = pool->idle;
active = pool->active;
busy = pool->busy;
pthread_mutex_unlock(&(pool->pool_lock));
if( idle < THREAD_POOL_MIN_IDLE_SIZE){
//less than preset idle thread then create new therad
if(active < pool->size){
//ok we can create new thread now
i = thread_pool_find_free_token(pool);
if(i == -1){
//sorry , it's unusual case
_DOL_FPRINTF_(stderr,"WARNING: can not found free token/n");
thread_pool_log("WARNING: can not found free token when create new thread");
}else{
rc = pthread_create(&(pool->token[i].thread_id), NULL, &thread_pool_serve, &(pool->token[i]));
if(rc !=0 ){
fprintf(stderr,"ERROR: thread pool create serve thread fail! code[%d] desc[%s]/n",errno,strerror(errno));
thread_pool_log("ERROR: thread pool create serve thread fail! code[%d] desc[%s]/n",errno,strerror(errno));
pthread_mutex_lock(&(pool->token[i].lock));
pool->token[i].state = TREAD_POOL_STATE_NOTRUN;
pthread_mutex_unlock(&(pool->token[i].lock));
}
usleep(CREATE_THREAD_SLEEP );
}
}else{
//sorry we're too busy
_DOL_FPRINTF_(stdout,"WARNING: no more idle thread, total:%d idle:%d busy:%d nrun:%d/n",active,idle,busy,active-idle-busy-1);
thread_pool_log("WARNING: we're busy, total:%d idle:%d busy:%d nrun:%d",active,idle,busy,active-idle-busy-1);
}
}
#ifdef _THREAD_POOL_JOB_LIST_
while(job_node = pop_job(pool)){
i = thread_pool_find_serve_token(pool);
if(i == -1){
/* we will break the loop if no more serve token found and push back the job */
push_job(pool,job_node);
break;
}else{
pthread_mutex_lock(&(pool->token[i].lock));
/* make the register thread safe */
if(pool->token[i].state == TREAD_POOL_STATE_IDLE){
pool->token[i].job = job_node;
/* set thread state to busy and the thread will process the job */
pool->token[i].state = TREAD_POOL_STATE_BUSY;
}else{
push_job(pool,job_node);
}
pthread_mutex_unlock(&(pool->token[i].lock));
}
}
#endif
usleep(LOOP_SLEEP );
}
/* wait for other serve thread to terminal */
while(pool->active > 1){
usleep(LOOP_SLEEP );
}
thread_pool_clean_up_lock(pool);
thread_pool_log("thread pool manage thread terminal! pid:%d ppid:%d",(int)getpid(),(int)getppid());
pool->active --;
return NULL;
}
void thread_pool_set_log(char* log_file){
if(log_file == NULL)
return;
if(strlen(log_file) > sizeof(real_log_file))
return;
strcpy(real_log_file,log_file);
}
/* thread pool log */
static void thread_pool_log(char* fmt, ...){
va_list args;
FILE * fo;
char date[32], ttime[32], filename[128], fpath[128];
char buffer[1024];
time_t tnow;
struct tm * tm_time;
time(&tnow);
tm_time = localtime(&tnow);
strftime(date, sizeof(date), "%y%m%d", tm_time);
strftime(ttime, sizeof(ttime), "%H%M%S", tm_time);
sprintf(filename, "%s", real_log_file);
//if(access(filename, F_OK) != 0){
//mkdir(fpath, 00777);
//chmod(fpath, 00777);
//}
//chmod(filename, 00666);
if((fo = fopen(filename, "a")) == 0){
fprintf(stderr,"cannot open %s", fo);
return;
}
va_start(args,fmt);
vsprintf(buffer,fmt,args);
fprintf(fo,"%s %s/n",ttime,buffer);
va_end(args);
fclose(fo);
}
int thread_pool_init(thread_pool_t * pool, int pool_size){
int rc,i;
pthread_t tid;
if(pool == NULL){
return ETPNOUSE;
}
memset(pool,0x00,sizeof(thread_pool_t));
memset(real_log_file,0x00,sizeof(real_log_file));
sprintf(real_log_file,"%s",default_log_file);
/* at least */
if(pool_size < THREAD_POOL_MIN_SIZE)
pool_size = THREAD_POOL_DEFAULT_SIZE;
else if(pool_size >= THREAD_POOL_MAX_SIZE )
pool_size = THREAD_POOL_MAX_SIZE;
pool->size = pool_size;
thread_pool_log("thread pool init with size:%d",pool->size);
pthread_mutex_init(&(pool->pool_lock),NULL);
#ifdef _THREAD_POOL_JOB_LIST_
pthread_mutex_init(&(pool->job_lock),NULL);
pool->job_head = NULL;
#endif
for(i=0;i<pool_size;i++){
pthread_mutex_init(&(pool->token[i].lock),NULL);
pool->token[i].token_id = i;
pool->token[i].state = TREAD_POOL_STATE_NOTRUN;
pool->token[i].job = NULL;
pool->token[i].pool = pool;
}
/* only create the manager thread, and it will create other serve threads */
rc = pthread_create(&tid, NULL, &thread_pool_manage, pool);
if(rc !=0 ){
fprintf(stderr,"ERROR:thread pool create fail! code[%d] desc[%s]/n",errno,strerror(errno));
thread_pool_log("ERROR:thread pool create fail! code[%d] desc[%s]/n",errno,strerror(errno));
pthread_mutex_destroy(&(pool->pool_lock));
#ifdef _THREAD_POOL_JOB_LIST_
pthread_mutex_destroy(&(pool->job_lock));
#endif
for(i=0;i<pool_size;i++){
pthread_mutex_destroy(&(pool->token[i].lock));;
}
return ETPERR;
}else{
_DOL_FPRINTF_(stdout,"thread pool create manage thread %u completed/n",tid);
}
usleep(CREATE_THREAD_SLEEP);
return ETPOK;
}
void thread_pool_destroy(thread_pool_t * pool){
if(pool == NULL)
return;
pool->quit = 1;
while(pool->active){
usleep(LOOP_SLEEP );
_DOL_FPRINTF_(stdout,"Still have %d threads in thread pool/n",pool->active);
}
#ifdef _THREAD_POOL_JOB_LIST_
destroy_job_list(pool->job_head);
#endif
thread_pool_log("thread pool destroy! terminal %d threads; total %d jobs",pool->size, pool->total_job);
}
int thread_pool_register_job(thread_pool_t * pool, job_call_back_t call_back, void * param, char* desc ){
int i=0,rc;
thread_pool_job_t* job = (thread_pool_job_t*)malloc(sizeof(thread_pool_job_t));
if(job == NULL){
/* no more memory */
return TREAD_POOL_REG_ERR;
}
memset(job,0x00,sizeof(thread_pool_job_t));
job->call_back = call_back;
job->param = param;
if(desc)
sprintf(job->desc,"%s",desc);
else
sprintf(job->desc,"N/A");
i = thread_pool_find_serve_token(pool);
if(i == -1){
#ifdef _THREAD_POOL_JOB_LIST_
job->next = NULL;
push_job(pool,job);
return TREAD_POOL_REG_OK;
#else
if(job)
free(job);
pool->reg_err ++;
return TREAD_POOL_REG_ERR_FULL;
#endif
}
pthread_mutex_lock(&(pool->token[i].lock));
/* make the register thread safe */
if(pool->token[i].state == TREAD_POOL_STATE_IDLE){
pool->token[i].job = job;
/* set thread state to busy and the thread will process the job */
pool->token[i].state = TREAD_POOL_STATE_BUSY;
rc = TREAD_POOL_REG_OK;
}else{
pool->reg_err ++;
rc = TREAD_POOL_REG_ERR;
}
pthread_mutex_unlock(&(pool->token[i].lock));
return rc;
}
static void thread_pool_clean_up_lock(thread_pool_t * pool){
int i;
if(pool == NULL)
return;
for(i=0; i<pool->size; i++){
pthread_mutex_destroy(&(pool->token[i].lock));
}
pthread_mutex_destroy(&(pool->pool_lock));
#ifdef _THREAD_POOL_JOB_LIST_
pthread_mutex_destroy(&(pool->job_lock));
#endif
}
void thread_pool_statistic(thread_pool_t * pool){
if(pool == NULL){
_DOL_FPRINTF_(stderr,"thread_pool_statistic(NULL)/n");
return;
}
fprintf(stdout,"/n *** thread pool statistic ***/n");
fprintf(stdout," size:%d/t job:%d/t reg_err:%d/n active:%d/t busy:%d/t idle:%d/t/n"
,pool->size,pool->total_job,pool->reg_err,pool->active,pool->busy,pool->idle);
}
void thread_pool_runtime(thread_pool_t * pool){
int i;
thread_pool_job_t* job;
char state[16];
if(pool == NULL){
_DOL_FPRINTF_(stderr,"thread_pool_runtime(NULL)/n");
return;
}
pthread_mutex_lock(&(pool->pool_lock));
fprintf(stdout,"/n *** thread pool runtime ***");
fprintf(stdout,"/n size:%d/t job:%d/t reg_err:%d/n active:%d/t busy:%d/t idle:%d/t/n"
,pool->size,pool->total_job,pool->reg_err,pool->active,pool->busy,pool->idle);
pthread_mutex_unlock(&(pool->pool_lock));
fprintf(stdout,"/n id/t tid/t job/t stat/t desc/n");
for(i=0; i<pool->size; i++){
pthread_mutex_lock(&(pool->token[i].lock));
if(pool->token[i].state != TREAD_POOL_STATE_NOTRUN){
fprintf(stdout, " %d/t %u/t %d/t ",
pool->token[i].token_id,pool->token[i].thread_id,pool->token[i].total_job);
if(pool->token[i].state == TREAD_POOL_STATE_NOTRUN){
sprintf(state,"NOTRUN");
}else if(pool->token[i].state == TREAD_POOL_STATE_IDLE){
sprintf(state,"IDLE");
}else if(pool->token[i].state == TREAD_POOL_STATE_BUSY){
sprintf(state,"BUSY");
}else{
sprintf(state,"UNKNW");
}
if(pool->token[i].job){
fprintf(stdout, "%s/t %s/n",state,(pool->token[i].job)->desc);
}else{
fprintf(stdout, "%s/t N/A/n",state);
}
}
pthread_mutex_unlock(&(pool->token[i].lock));
}
#ifdef _THREAD_POOL_JOB_LIST_
pthread_mutex_lock(&(pool->job_lock));
job = pool->job_head;
while(job){
fprintf(stdout," N/A/t N/A/t N/A/t STDBY/t %s/n",job->desc);
job = job->next;
}
pthread_mutex_unlock(&(pool->job_lock));
#endif
}
static int thread_pool_find_free_token(thread_pool_t * pool){
int idx = -1, i;
if(pool == NULL)
return -1;
for(i=0; i < pool->size; i++ ){
pthread_mutex_lock(&(pool->token[i].lock));
if(pool->token[i].state == TREAD_POOL_STATE_NOTRUN){
idx = i;
}
pthread_mutex_unlock(&(pool->token[i].lock));
if(idx != -1)
break;
}
return idx;
}
static int thread_pool_find_serve_token(thread_pool_t * pool){
int idx = -1, i = 0;
if(pool == NULL)
return -1;
for(i=0; i<pool->size; i++ ){
pthread_mutex_lock(&(pool->token[i].lock));
if(pool->token[i].state == TREAD_POOL_STATE_IDLE){
idx = i;
}
pthread_mutex_unlock(&(pool->token[i].lock));
if(idx != -1)
break;
}
return idx;
}
#ifdef _THREAD_POOL_JOB_LIST_
static thread_pool_job_t* pop_job(thread_pool_t * pool){
thread_pool_job_t* job_node = NULL;
if(pool){
pthread_mutex_lock(&(pool->job_lock));
job_node = pool->job_head;
if(job_node && job_node->next){
pool->job_head = job_node->next;
job_node->next = NULL;
}else{
pool->job_head = NULL;
}
pthread_mutex_unlock(&(pool->job_lock));
}
return job_node;
}
static void push_job(thread_pool_t * pool, thread_pool_job_t* job){
if(job == NULL)
return;
if(pool){
pthread_mutex_lock(&(pool->job_lock));
job->next = pool->job_head;
pool->job_head = job;
pthread_mutex_unlock(&(pool->job_lock));
}
return;
}
static void destroy_job_list(thread_pool_job_t* job_head){
thread_pool_job_t* job_node ;
while(job_head){
job_node = job_head;
job_head = job_head->next;
free(job_node);
}
job_head = NULL;
return;
}
#endif
3. thread_pool.def
#ifndef _THREAD_POOL_DEF_
#define _THREAD_POOL_DEF_
#ifndef _THREAD_POOL_JOB_LIST_
#define _THREAD_POOL_JOB_LIST_
#endif
//#ifndef _DEBUG_VERSION_
//#define _DEBUG_VERSION_
//#endif
#endif //end define _THREAD_POOL_DEF_
4.Makefile
obj=thread_pool.o
src=thread_pool.c
inc=thread_pool.h
def=thread_pool.def
target=$(obj)
.PHONY: all
.PHONY: clean
.PHONY: lib
all: $(target)
@echo "Building Dolphin's Libaray"
$(obj): $(src) $(inc) $(def)
gcc -g -c -fPIC $< -o $@
clean:
rm -f *.o *.so *.a
lib: $(target)
gcc -shared -fPIC -o libdol.so $(target)
ar cr libdol.a $(target)
以上便是主要的源代码。
下面给出一个使用该线程池的例子:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include "thread_pool.h"
int quit =0;
void sig_handler(int sig_no){
quit = 1;
}
void call_back_func(void * arg ){
int p = (int)(void*)arg;
int i=0;
while(!quit){
//fprintf(stdout,"%-3d alive/n",p);
sleep(1);
break;
}
}
int main(int argc, char** argv){
thread_pool_t pool;
job_call_back_t call_back;
int i,rc;
char desc [64];
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
rc = thread_pool_init(&pool, 5);
thread_pool_set_log("./test_tp.log");
if(rc != ETPOK){
fprintf(stderr,"thread_pool_init fail/n");
return 1;
}
sleep(2);
call_back = call_back_func;
for(i=0;i<10;i++){
sprintf(desc,"job %d",i);
//sleep(1);
rc = thread_pool_register_job(&pool, call_back, (void*)i, desc);
if(rc != TREAD_POOL_REG_OK){
fprintf(stderr,"regiser %d %s fail/n",i,desc);
}
}
while(!quit){
thread_pool_runtime(&pool);
sleep(1);
}
thread_pool_destroy(&pool);
fprintf(stdout,"program stoping!/n");
return 0;
}
Makefile:
exe=test_tp
src=test_tp.c
obj=test_tp.o
.PHONY: all
.PHONY: clean
all: $(exe)
clean:
rm -f $(exe) $(obj)
$(exe): $(obj)
gcc -g $^ -o $@ -lpthread -L.. -ldol
$(obj): $(src)
gcc -g -c $< -o $@ -I..