00001
00002 #include <eh_utils.h>
00003 #include <pthread.h>
00004
00005 void
00006 tpool_init(tpool_t *tpoolp, int num_worker_threads, int max_queue_size, int do_not_block_when_full)
00007 {
00008 int i, rtn;
00009 tpool_t tpool;
00010 pthread_attr_t attr;
00011
00012 pthread_attr_init( &attr );
00013 pthread_attr_setscope( &attr , PTHREAD_SCOPE_SYSTEM );
00014
00015
00016
00017
00018 tpool = eh_new( struct tpool , 1 );
00019
00020 tpool->num_threads = num_worker_threads;
00021 tpool->max_queue_size = max_queue_size;
00022 tpool->do_not_block_when_full = do_not_block_when_full;
00023
00024
00025 tpool->threads = eh_new( pthread_t , num_worker_threads );
00026
00027 tpool->cur_queue_size = 0;
00028 tpool->queue_head = NULL;
00029 tpool->queue_tail = NULL;
00030 tpool->queue_closed = 0;
00031 tpool->shutdown = 0;
00032 if ( (rtn=pthread_mutex_init(&(tpool->queue_lock),NULL)) != 0 )
00033 fprintf(stderr,"pthread_mutex_init %s",strerror(rtn)), eh_exit(-1);
00034 if ( (rtn=pthread_cond_init(&(tpool->queue_not_empty),NULL)) != 0 )
00035 fprintf(stderr,"pthread_cond_init %s",strerror(rtn)), eh_exit(-1);
00036 if ( (rtn=pthread_cond_init(&(tpool->queue_not_full),NULL)) != 0 )
00037 fprintf(stderr,"pthread_cond_init %s",strerror(rtn)), eh_exit(-1);
00038 if ( (rtn=pthread_cond_init(&(tpool->queue_empty),NULL)) != 0 )
00039 fprintf(stderr,"pthread_cond_init %s",strerror(rtn)), eh_exit(-1);
00040
00041 for ( i=0 ; i!=num_worker_threads ; i++ )
00042 if ( (rtn=pthread_create( &(tpool->threads[i]) , &attr , (void *(*)(void*))tpool_thread , (void*)tpool )) != 0 )
00043 fprintf(stderr,"pthread_create %d",rtn), eh_exit(-1);
00044
00045 pthread_attr_destroy(&attr);
00046
00047 *tpoolp = tpool;
00048 }
00049
00050 void
00051 tpool_thread( tpool_t tpool )
00052 {
00053 tpool_work_t *my_workp;
00054
00055 for (;;)
00056 {
00057 pthread_mutex_lock( &(tpool->queue_lock) );
00058 while ( (tpool->cur_queue_size==0) && (!tpool->shutdown) )
00059 {
00060 pthread_cond_wait( &(tpool->queue_not_empty) , &(tpool->queue_lock) );
00061 }
00062
00063 if ( tpool->shutdown )
00064 {
00065 pthread_mutex_unlock( &(tpool->queue_lock) );
00066 pthread_exit( NULL );
00067 }
00068
00069 my_workp = tpool->queue_head;
00070 tpool->cur_queue_size--;
00071 if ( tpool->cur_queue_size == 0 )
00072 tpool->queue_head = tpool->queue_tail = NULL;
00073 else
00074 tpool->queue_head = my_workp->next;
00075
00076 if ( (!tpool->do_not_block_when_full) && (tpool->cur_queue_size==(tpool->max_queue_size-1)) )
00077 pthread_cond_broadcast( &(tpool->queue_not_full) );
00078
00079 if ( tpool->cur_queue_size == 0 )
00080 pthread_cond_signal( &(tpool->queue_empty) );
00081
00082 pthread_mutex_unlock( &(tpool->queue_lock) );
00083 (*(my_workp->routine))(my_workp->arg);
00084 eh_free(my_workp);
00085 }
00086 }
00087
00088 int
00089 tpool_add_work( tpool_t tpool , void *routine , void *arg )
00090 {
00091 tpool_work_t *workp;
00092 pthread_mutex_lock( &(tpool->queue_lock) );
00093
00094 if ( ( tpool->cur_queue_size==tpool->max_queue_size )
00095 && tpool->do_not_block_when_full )
00096 {
00097 pthread_mutex_unlock( &(tpool->queue_lock) );
00098 return -1;
00099 }
00100
00101 while ( ( tpool->cur_queue_size==tpool->max_queue_size )
00102 && ( !(tpool->shutdown || tpool->queue_closed) ) )
00103 {
00104 pthread_cond_wait( &(tpool->queue_not_full) , &(tpool->queue_lock) );
00105 }
00106
00107 if ( tpool->shutdown || tpool->queue_closed )
00108 {
00109 pthread_mutex_unlock( &(tpool->queue_lock) );
00110 return -1;
00111 }
00112
00113
00114 workp = eh_new( tpool_work_t , 1 );
00115 workp->routine = (void(*)())routine;
00116 workp->arg = arg;
00117 workp->next = NULL;
00118 if ( tpool->cur_queue_size == 0 )
00119 {
00120 tpool->queue_tail = tpool->queue_head = workp;
00121 pthread_cond_broadcast( &(tpool->queue_not_empty) );
00122 }
00123 else
00124 {
00125 (tpool->queue_tail)->next = workp;
00126 tpool->queue_tail = workp;
00127 }
00128 tpool->cur_queue_size++;
00129
00130 pthread_mutex_unlock( &(tpool->queue_lock) );
00131 return 1;
00132 }
00133
00134 int
00135 tpool_destroy( tpool_t tpool , int finish )
00136 {
00137 int i, rtn;
00138 tpool_work_t *cur_nodep;
00139
00140 if ( (rtn=pthread_mutex_lock( &(tpool->queue_lock) )) != 0 )
00141 fprintf(stderr,"pthread_mutex_lock %d",rtn), eh_exit(-1);
00142
00143 if ( tpool->queue_closed || tpool->shutdown )
00144 {
00145 if ( (rtn=pthread_mutex_unlock( &(tpool->queue_lock) )) != 0 )
00146 fprintf(stderr,"pthread_mutex_unlock %d",rtn), eh_exit(-1);
00147 return 0;
00148 }
00149
00150 tpool->queue_closed = 1;
00151
00152 if ( finish==1 )
00153 {
00154 while ( tpool->cur_queue_size!=0 )
00155 if ( (rtn=pthread_cond_wait( &(tpool->queue_empty) , &(tpool->queue_lock) )) != 0 )
00156 fprintf(stderr,"pthread_cond_wait %d",rtn), eh_exit(-1);
00157 }
00158
00159 tpool->shutdown = 1;
00160
00161 if ( (rtn=pthread_mutex_unlock( &(tpool->queue_lock) ))!=0 )
00162 fprintf(stderr,"pthread_mutex_unlock %d",rtn), eh_exit(-1);
00163
00164 if ( (rtn=pthread_cond_broadcast( &(tpool->queue_not_empty) ))!=0 )
00165 fprintf(stderr,"pthread_cond_broadcast %d",rtn), eh_exit(-1);
00166 if ( (rtn=pthread_cond_broadcast( &(tpool->queue_not_full) ))!=0 )
00167 fprintf(stderr,"pthread_cond_broadcast %d",rtn), eh_exit(-1);
00168
00169 for ( i=0 ; i<tpool->num_threads ; i++ )
00170 {
00171 if ( (rtn=pthread_join( tpool->threads[i] , NULL ))!=0 )
00172 fprintf(stderr,"pthread_join %d",rtn), eh_exit(-1);
00173 }
00174
00175 eh_free(tpool->threads);
00176 while ( tpool->queue_head != NULL )
00177 {
00178 cur_nodep = tpool->queue_head->next;
00179 tpool->queue_head = tpool->queue_head->next;
00180 eh_free(cur_nodep);
00181 }
00182 eh_free(tpool);
00183 return 0 ;
00184 }
00185