I have a queue of jobs and I want to make a pool of 4 threads where I can throw my jobs at. What I am stuck at is in how to make the threads and keep them suspended while there is no work.
JOB QUEUE | job1 | job2 | job3 | job4 | ..
THREAD POOL | thread1 | thread2 | thread3 | thread4 |
To create the threads I have currently at the initialisation point:
for (t=0; t<num_of_threads; t++){
pthread_create(&(threads[t]), NULL, doSth2, NULL);
}
Where num_of_threads=4 and doSth2 is a function with nothing inside.
So once I have created the 4 threads and they are done with doSth2, how can I give them new work to do, without killing them?
The key to a thread pool is a queue. Here are modified functions for a thread pool I have developed.
Put element in queue
void queue_add(queue q, void *value)
{
pthread_mutex_lock(&q->mtx);
/* Add element normally. */
pthread_mutex_unlock(&q->mtx);
/* Signal waiting threads. */
pthread_cond_signal(&q->cond);
}
Get element from queue
void queue_get(queue q, void **val_r)
{
pthread_mutex_lock(&q->mtx);
/* Wait for element to become available. */
while (empty(q))
rc = pthread_cond_wait(&q->cond, &q->mtx);
/* We have an element. Pop it normally and return it in val_r. */
pthread_mutex_unlock(&q->mtx);
}
As an alternate riff on cnicutar's answer you can just use POSIX message queues which will take care of the synchronization concerns in the kernel. There will be some small overhead for the system calls which may or may not be a concern. It is pretty minimal as the kernel is doing everything you would have to do manually anyway.
The consumer threads can just block on mq_receive
and if you create a special type of queue message it makes it easy to tell the threads when to shut down.