I used a thread pool, the main thread continuous add tasks into a queue, and throw a pthread_cond_signal that indicate the queue is not empty to the work threads. Then the work threads read the queue and throw a pthread_cond_signal indicate the queue is not full to the main thread. And when the program ran, I found the pthread_cond_wait is very slow, if I delete the pthread_cond_wait in function threadpool_add, it's much quicker, but I doubt it may has something wrong, How can I let the threadpool_add function faster? it's the performance bottleneck of my project, Here is the code:
/*
* @function int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg, char* buf)
* @desc add tasks to the queue
* @param [thread_num] number of thread in pool,
* [queue_max_size] size of the queue for task
*/
int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg)
{
ulogd_log(ULOGD_NOTICE, "in threadpool_add\n");
if(pool == NULL || function == NULL || arg == NULL)
{
return -1;
}
pthread_mutex_lock(&(pool->lock));
/*
* wait untill queue is not full
*/
while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown))
{
pthread_cond_wait(&(pool->queue_not_full), &(pool->lock)); // if delete this, it's quicker
}
if (pool->shutdown)
{
pthread_mutex_unlock(&(pool->lock));
return 0;
}
pool->task_queue[pool->queue_rear].function = function;
pool->task_queue[pool->queue_rear].arg = arg;
pool->queue_rear = (pool->queue_rear + 1)%pool->queue_max_size;
pool->queue_size++;
/*
* notify to the threads, there has a task
*/
pthread_cond_signal(&(pool->queue_not_empty));
pthread_mutex_unlock(&(pool->lock));
ulogd_log(ULOGD_NOTICE, "threadpool_add, tpool:0x%x, shutdown: %d, queue_size:%d, queue_not_empty:0x%x\n", pool, pool->shutdown, pool->queue_size, &(pool->queue_not_empty));
return 0;
}
void *threadpool_thread(void *threadpool)
{
threadpool_t *pool = (threadpool_t *)threadpool;
threadpool_task_t task;
while(1)
{
ulogd_log(ULOGD_NOTICE, "in thread 0x%x, tpool: 0x%x\n", pthread_self(), pool);
/* Lock must be taken to wait on conditional variable */
pthread_mutex_lock(&(pool->lock));
while ((pool->queue_size == 0) && (!pool->shutdown))
{
ulogd_log(ULOGD_NOTICE, "thread 0x%x is waiting, queue_size:%d, queue_not_empty:0x%x\n", pthread_self(), pool->queue_size, &(pool->queue_not_empty));
pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));
}
if (pool->shutdown)
{
pthread_mutex_unlock(&(pool->lock));
ulogd_log(ULOGD_NOTICE,"thread 0x%x is exiting\n", pthread_self());
pthread_exit(NULL);
}
//get a task from queue
task.function = pool->task_queue[pool->queue_front].function;
task.arg = pool->task_queue[pool->queue_front].arg;
pool->queue_front = (pool->queue_front + 1)%pool->queue_max_size;
pool->queue_size--;
//now queue must be not full
pthread_mutex_unlock(&(pool->lock));
pthread_cond_signal(&(pool->queue_not_full));
// Get to work
ulogd_log(ULOGD_NOTICE, "thread 0x%x start working\n", pthread_self());
(*(task.function))(task.arg);
// task run over
ulogd_log(ULOGD_NOTICE, "thread 0x%x end working\n", pthread_self());
}
pthread_exit(NULL);
return (NULL);
}