// Thrmgr. h
# Ifndef _ thrmgr_h __
# DEFINE _ thrmgr_h __
# Include <sys/time. h>
# Include <pthread. h>
Typedef struct work_item_tag
{
Struct work_item_tag * next;
Void * data;
Struct timeval time_queued;
} Work_item_t;
Typedef struct work_queue_tag
{
Work_item_t * head;
Work_item_t * tail;
Int item_count;
} Work_queue_t;
Typedef Enum
{
Pool_invalid,
Pool_valid,
Pool_exit,
} Pool_state_t;
Typedef struct threadpool_tag
{
Pthread_mutex_t pool_mutex;
Pthread_cond_t pool_cond;
Pthread_attr_t pool_attr;
Pool_state_t state;
Int thr_max;
Int thr_alive;
Int thr_idle;
Int idle_timeout;
Void (* Handler) (void *);
Work_queue_t * queue;
} Threadpool_t;
Threadpool_t * thrmgr_new (INT max_threads, int idle_timeout, void (* Handler) (void *));
Void thrmgr_destroy (threadpool_t * threadpool );
Int thrmgr_dispatch (threadpool_t * threadpool, void * user_data );
# Endif
// Thrmgr. c
# Include "thrmgr. H"
# Include <stdlib. h>
# Include <memory. h>
# Include <errno. h>
# Define false (0)
# Define true (1)
Work_queue_t * work_queue_new ()
{
Work_queue_t * work_q;
Work_q = (work_queue_t *) malloc (sizeof (work_queue_t ));
Work_q-> head = work_q-> tail = NULL;
Work_q-> item_count = 0;
Return work_q;
}
Void work_queue_add (work_queue_t * work_q, void * Data)
{
Work_item_t * work_item;
If (! Work_q)
{
Return;
}
Work_item = (work_item_t *) malloc (sizeof (work_item_t ));
Work_item-> next = NULL;
Work_item-> DATA = data;
Gettimeofday (& (work_item-> time_queued), null );
If (work_q-> head = NULL)
{
Work_q-> head = work_q-> tail = work_item;
Work_q-> item_count = 1;
}
Else
{
Work_q-> tail-> next = work_item;
Work_q-> tail = work_item;
Work_q-> item_count ++;
}
Return;
}
Void * work_queue_pop (work_queue_t * work_q)
{
Work_item_t * work_item;
Void * data;
If (! Work_q |! Work_q-> head)
{
Return NULL;
}
Work_item = work_q-> head;
Data = work_item-> data;
Work_q-> head = work_item-> next;
If (work_q-> head = NULL)
{
Work_q-> tail = NULL;
}
Free (work_item );
Return data;
}
Void thrmgr_destroy (threadpool_t * threadpool)
{
If (! Threadpool | (threadpool-> state! = Pool_valid ))
{
Return;
}
If (pthread_mutex_lock (& threadpool-> pool_mutex )! = 0)
{
// Logg ("! Mutex lock failed/N ");
Exit (-1 );
}
Threadpool-> state = pool_exit;
/* Wait For threads to exit */
If (threadpool-> thr_alive> 0)
{
If (pthread_cond_broadcast (& (threadpool-> pool_cond ))! = 0)
{
Pthread_mutex_unlock (& threadpool-> pool_mutex );
Return;
}
}
While (threadpool-> thr_alive> 0)
{
If (pthread_cond_wait (& threadpool-> pool_cond, & threadpool-> pool_mutex )! = 0)
{
Pthread_mutex_unlock (& threadpool-> pool_mutex );
Return;
}
}
If (pthread_mutex_unlock (& threadpool-> pool_mutex )! = 0)
{
// Logg ("! Mutex unlock failed/N ");
Exit (-1 );
}
Pthread_mutex_destroy (& (threadpool-> pool_mutex ));
Pthread_cond_destroy (& (threadpool-> pool_cond ));
Pthread_attr_destroy (& (threadpool-> pool_attr ));
Free (threadpool );
Return;
}
Threadpool_t * thrmgr_new (INT max_threads, int idle_timeout, void (* Handler) (void *))
{
Threadpool_t * threadpool;
If (max_threads <= 0)
{
Return NULL;
}
Threadpool = (threadpool_t *) malloc (sizeof (threadpool_t ));
Threadpool-> queue = work_queue_new ();
If (! Threadpool-> Queue)
{
Free (threadpool );
Return NULL;
}
Threadpool-> thr_max = max_threads;
Threadpool-> thr_alive = 0;
Threadpool-> thr_idle = 0;
Threadpool-> idle_timeout = idle_timeout;
Threadpool-> handler = handler;
Pthread_mutex_init (& (threadpool-> pool_mutex), null );
If (pthread_cond_init (& (threadpool-> pool_cond), null )! = 0)
{
Free (threadpool );
Return NULL;
}
If (pthread_attr_init (& (threadpool-> pool_attr ))! = 0)
{
Free (threadpool );
Return NULL;
}
If (pthread_attr_setdetachstate (& (threadpool-> pool_attr), pthread_create_detached )! = 0)
{
Free (threadpool );
Return NULL;
}
Threadpool-> state = pool_valid;
Return threadpool;
}
Void * thrmgr_worker (void * Arg)
{
Threadpool_t * threadpool = (threadpool_t *) ARG;
Void * job_data;
Int retval, must_exit = false;
Struct timespec timeout;
/* Loop looking for work */
For (;;)
{
If (pthread_mutex_lock (& (threadpool-> pool_mutex ))! = 0)
{
/* Fatal error */
// Logg ("! Fatal: mutex lock failed/N ");
Exit (-2 );
}
Timeout. TV _sec = Time (null) + threadpool-> idle_timeout;
Timeout. TV _nsec = 0;
Threadpool-> thr_idle ++;
While (job_data = work_queue_pop (threadpool-> Queue) = NULL) & (threadpool-> state! = Pool_exit ))
{
// Sleep, awaiting wakeup,
Retval = pthread_cond_timedwait (& (threadpool-> pool_cond), & (threadpool-> pool_mutex), & timeout );
If (retval = etimedout)
{
Must_exit = true;
Break;
}
}
Threadpool-> thr_idle --;
If (threadpool-> state = pool_exit)
{
Must_exit = true;
}
If (pthread_mutex_unlock (& (threadpool-> pool_mutex ))! = 0)
{
/* Fatal error */
// Logg ("! Fatal: mutex unlock failed/N ");
Exit (-2 );
}
If (job_data)
{
Threadpool-> handler (job_data );
}
Else if (must_exit)
{
Break;
}
}
If (pthread_mutex_lock (& (threadpool-> pool_mutex ))! = 0)
{
/* Fatal error */
// Logg ("! Fatal: mutex lock failed/N ");
Exit (-2 );
}
Threadpool-> thr_alive --;
If (threadpool-> thr_alive = 0)
{
/* Signal that all threads are finished */
Pthread_cond_broadcast (& threadpool-> pool_cond );
}
If (pthread_mutex_unlock (& (threadpool-> pool_mutex ))! = 0)
{
/* Fatal error */
// Logg ("! Fatal: mutex unlock failed/N ");
Exit (-2 );
}
Return NULL;
}
Int thrmgr_dispatch (threadpool_t * threadpool, void * user_data)
{
Pthread_t thr_id;
If (! Threadpool)
{
Return false;
}
/* Lock the threadpool */
If (pthread_mutex_lock (& (threadpool-> pool_mutex ))! = 0)
{
// Logg ("! Mutex lock failed/N ");
Return false;
}
If (threadpool-> state! = Pool_valid)
{
If (pthread_mutex_unlock (& (threadpool-> pool_mutex ))! = 0)
{
// Logg ("! Mutex unlock failed/N ");
Return false;
}
Return false;
}
Work_queue_add (threadpool-> queue, user_data );
// Create a thread only when there is no thread idle and the number of threads currently generated is smaller than the maximum number of threads required
If (threadpool-> thr_idle = 0) & (threadpool-> thr_alive <threadpool-> thr_max ))
{
/* Start a new thread */
If (pthread_create (& thr_id, & (threadpool-> pool_attr), thrmgr_worker, threadpool )! = 0)
{
// Logg ("! Pthread_create failed/N ");
}
Else
{
Threadpool-> thr_alive ++;
}
}
/* Release the conditional signal. If there is a thread waiting for the signal, the thread runs */
Pthread_cond_signal (& (threadpool-> pool_cond ));
If (pthread_mutex_unlock (& (threadpool-> pool_mutex ))! = 0)
{
// Logg ("! Mutex unlock failed/N ");
Return false;
}
Return true;
}
/*
The following describes how to use a TCP server,
1. thrmgr_new
2, while (1)
{
Accept (......);
// Construct input parameters
Thrmgr_dispach (...);
}
Thrmgr_destory (...);
Int main ()
{
Threadpool_t * threadpool = thrmgr_new (5, 0, handle );
Thrmgr_dispatch (threadpool, (void *) 5 );
Thrmgr_dispatch (threadpool, (void *) 7 );
Thrmgr_destroy (threadpool );
}
*/