
《UNIX网络编程》卷I的后部分,有2种 线程池实现方式,一种是主线程预先创建线程,然后统一accept;另一种是主线程创建N个线程,各自accept。
线程池中的每个线程,当没有任务时,是阻塞在那里睡觉的;在Stevens大师的实现中,accept的返回就成了唤醒它们的契机。
这回我工作中遇到另外一种需求,就是在每个线程中使用一个定时器,timer。由于alarm、setitimer + sigaction等信号处理方式在多线程环境下会彼此干扰,所以需要使用posix实时扩展库的API。下面是具体实现中的与公司业务无关的部分代码,大家帮忙挑挑错。
头文件:
//filename: tpoll.h
#ifndef _TPOOL_H
#define _TPOOL_H
#define DEBUG(i) { if(i != 0) { fprintf(stderr,"LINE:%d , error:%s\n",__LINE__, strerror(i) ); exit(1); } }
typedef struct my {
pthread_t tid;
} my_struct_t;
#define MAX_PTHREADS 50
#define MAX_TASKS 100
#endif
main.c文件:
//filename:main.c
/* a simple implementation of pthread pool, using timers
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "tpool.h"
// the only signal used in this program
#define SIGMYTIMER (SIGRTMAX)
//for timers
timer_t timer_vec[MAX_TASKS];
//for pthreads
my_struct_t my_array[MAX_PTHREADS];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int task_vec[MAX_TASKS];
int iget,iput;
//for timers
timer_t my_timer_create(int elaspe,int idx);
void my_handler(int signo, siginfo_t *info, void *context);
//for pthreads
void *start_routine(void *ptr);
int main(int argc,char** argv)
{
/* ###################################################### */
/* ########### TIMERS ################# */
/* ###################################################### */
iput = iget = 0;
//====>>>> BEGIN
int j;
timer_t tid;
for(j = 0; j < MAX_TASKS; j++) {
/* FIXME: pass your timer-interval to my_timer_create(), */
tid = my_timer_create(3*j,j);
if(tid == -1) {
/* TODO:error handling */
}
timer_vec[j] = tid;
}
struct sigaction sysact;
sigemptyset(&sysact.sa_mask);
sysact.sa_flags = SA_SIGINFO;
sysact.sa_sigaction = my_handler;
// perform the install
sigaction(SIGMYTIMER, &sysact, NULL);
//<<<<==== END
/* ###################################################### */
/* ############### PTHREAD POOL ################# */
/* ###################################################### */
//====>>>> BEGIN
int err;
int ii;
for(ii = 0; ii < MAX_PTHREADS; ii++) {
err = pthread_create(&my_array[ii].tid, NULL,
start_routine, (void *)ii);
DEBUG(err);
}
//<<<<==== END
while(1)
sleep(10);
return 0;
}
/* the first argument represents the interval */
timer_t my_timer_create(int elaspe,int idx)
{
timer_t retval;
struct sigevent evp;
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGMYTIMER;
evp.sigev_value.sival_ptr = &timer_vec[idx];
int result = timer_create(CLOCK_REALTIME, &evp, &retval) ;
if(result == 0) {//succeeded
struct itimerspec value;
struct itimerspec ovalue;
value.it_value.tv_sec = elaspe;
value.it_value.tv_nsec = 0;
// persist timer
value.it_interval.tv_sec = value.it_value.tv_sec;
value.it_interval.tv_nsec = value.it_value.tv_nsec;
//set time
if(timer_settime(retval, 0, &value, &ovalue) == 0) {
/*cout<<"LINE-"<<__LINE__<<" timer_id:"<si_value.sival_ptr))
<<" "<<"signo:"<si_value.sival_ptr), signo);
int err;
err = pthread_mutex_lock(&mutex);
DEBUG(err);
//===>>> BEGIN
int timer_id = *((int *)(info->si_value.sival_ptr));
task_vec[iput] = timer_id;
if( ++iput == MAX_PTHREADS)
iput = 0;
if(iput == iget) {
/* TODO: */
}
//<<<=== END
err = pthread_cond_signal(&cond);
DEBUG(err);
err = pthread_mutex_unlock(&mutex);
DEBUG(err);
}
void *start_routine(void *ptr)
{
pthread_detach(pthread_self());
int ert = 0;
int idx = (int)ptr;
//cout<<"i'm thread-"<