pthread_cond_t cond_queue_empty, cond_queue_full; 
pthread_mutex_t task_queue_cond_lock; 
int task_available; 
 
/* other data structures here */ 
 
main() { 
  /* declarations and initializations */ 
  task_available = 0; 
  pthread_init(); 
  pthread_cond_init(&cond_queue_empty, NULL); 
  pthread_cond_init(&cond_queue_full, NULL); 
  pthread_mutex_init(&task_queue_cond_lock, NULL); 
  /* create and join producer and consumer threads */ 
} 
 
void *producer(void *producer_thread_data) { 
  int inserted; 
  while (!done()) { 
    create_task(); 
    pthread_mutex_lock(&task_queue_cond_lock); 
    while (task_available == 1) 
      pthread_cond_wait(&cond_queue_empty, 
			&task_queue_cond_lock); 
    insert_into_queue(); 
    task_available = 1; 
    pthread_cond_signal(&cond_queue_full); 
    pthread_mutex_unlock(&task_queue_cond_lock); 
  } 
} 
 
void *consumer(void *consumer_thread_data) { 
  while (!done()) { 
    pthread_mutex_lock(&task_queue_cond_lock); 
    while (task_available == 0) 
      pthread_cond_wait(&cond_queue_full, 
			&task_queue_cond_lock); 
    my_task = extract_from_queue(); 
    task_available = 0; 
    pthread_cond_signal(&cond_queue_empty); 
    pthread_mutex_unlock(&task_queue_cond_lock); 
    process_task(my_task); 
  } 
} 
