24

I have a queue of jobs and I want to make a pool of four 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?

jww
  • 97,681
  • 90
  • 411
  • 885
Pithikos
  • 18,827
  • 15
  • 113
  • 136

2 Answers2

21

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);
}
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • Thank you. I get the idea now.. Each thread in the pool is supposed to read from the queue serially. Though how do you go with pausing the threads if the queue is empty so that they don't eat up the cpu? – Pithikos Aug 05 '11 at 10:16
  • @Pithikos `pthread_cond_wait` blocks until someone (`queue_add`) signals `cond`. – cnicutar Aug 05 '11 at 10:17
  • 1
    Sorry to open this so late but if the queue_get is locking the mtx and then looping, how can you add an item if mtx is locked? Shouldn't the lock be *after* the loop (e.g. loop -> lock -> pop -> unlock)? – Alexandre Gomes Oct 22 '14 at 19:44
  • 2
    A while ago I know - to answer @AlexandreGomes - pthread_cond_wait (from man [http://linux.die.net/man/3/pthread_cond_wait]) unlocks the mutex while waiting, for other thread to use, and returns having locked it again. Hence the mutex is passed as a parameter. – Dazed Jan 11 '16 at 12:00
4

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.

Duck
  • 26,924
  • 5
  • 64
  • 92