If there is a task available, the consumer takes it off the work queue and signals the producer. In this way, the producer and consumer threads operate by signaling each other. It is easy to see that this mode of operation is similar to an interrupt-based operation as opposed to a polling-based operation of pthread_mutex_trylock.
1 pthread_cond_t cond_queue_empty, cond_queue_full;
2 pthread_mutex_t task_queue_cond_lock;
3 int task_available;
4
5 /* other data structures here */
6
7 main() {
8 /* declarations and initializations */
9 task_available = 0;
10 pthread_init();
11 pthread_cond_init(&cond_queue_empty, NULL);
12 pthread_cond_init(&cond_queue_full, NULL);
13 pthread_mutex_init(&task_queue_cond_lock, NULL);
14 /* create and join producer and consumer threads */
15 }
16
17 void *producer(void *producer_thread_data) {
18 int inserted;
19 while (!done()) {
20 create_task();
21 pthread_mutex_lock(&task_queue_cond_lock);
22 while (task_available == 1)
23 pthread_cond_wait(&cond_queue_empty,
24 &task_queue_cond_lock);
25 insert_into_queue();
26 task_available = 1;
27 pthread_cond_signal(&cond_queue_full);
28 pthread_mutex_unlock(&task_queue_cond_lock);
29 }
30 }
31
32 void *consumer(void *consumer_thread_data) {
33 while (!done()) {
34 pthread_mutex_lock(&task_queue_cond_lock);
35 while (task_available == 0)
36 pthread_cond_wait(&cond_queue_full,
37 &task_queue_cond_lock);
38 my_task = extract_from_queue();
39 task_available = 0;
40 pthread_cond_signal(&cond_queue_empty);
41 pthread_mutex_unlock(&task_queue_cond_lock);
42 process_task(my_task);
43 }
44 }