All pastes #411934 Raw Edit

Someone

public c v1 · immutable
#411934 ·published 2007-03-27 11:39 UTC
rendered paste body
#include <stdio.h>#include <stdlib.h>#include <pthread.h>/* these signal which thread has its turn to execute */enum{  THREAD1_OK_TO_GO,  THREAD2_OK_TO_GO,  THREAD3_OK_TO_GO};/* the wait queue variable needs to be set * before threads execute */int queue = THREAD1_OK_TO_GO;void *thread1_func (void*);void *thread2_func (void*);void *thread3_func (void*);/* mutex and cond for queue handling */pthread_mutex_t cond_mutex1 = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t  cond1       = PTHREAD_COND_INITIALIZER;intmain (void){  pthread_t thread1, thread2, thread3;  /* we'll create the threads in reverse order to demonstrate   * that the queueing works in spite of it   */  pthread_create (&thread3, NULL, thread3_func, NULL);  pthread_create (&thread2, NULL, thread2_func, NULL);  pthread_create (&thread1, NULL, thread1_func, NULL);  /* we'll wait for the threads to join, which in this case   * will never happen because they loop indefinitely, but   * that's OK for our purposes   */  pthread_join (thread1, NULL);  pthread_join (thread2, NULL);  pthread_join (thread3, NULL);  return 0;}/* notice that the thread functions are nearly identical, so the * second and third one don't need much further commenting */void*thread1_func (void *ptr){  int i;  while (1)    {      /* lock the queue check to prevent races, then wait       * for our turn       */      pthread_mutex_lock (&cond_mutex1);      while (queue != THREAD1_OK_TO_GO)        pthread_cond_wait (&cond1, &cond_mutex1);      pthread_mutex_unlock (&cond_mutex1);      /* notice that we don't need a separate mutex for the       * relevant part because it's conveniently sandwiched        * in between the queue handling code       */      putchar ('1');      /* after we're done we specify who goes next, then       * signal the other threads that they can proceed.       * 3 or more threads requires pthread_cond_broadcast(),       * for only 2 threads we could use pthread_cond_signal().       * note that locking is absolutely necessary here too!       */      pthread_mutex_lock (&cond_mutex1);      queue = THREAD2_OK_TO_GO;      pthread_cond_broadcast (&cond1);      pthread_mutex_unlock (&cond_mutex1);    }}/* differing parts are commented */void*thread2_func (void *ptr){  int i;  while (1)    {      /* notice that we're now waiting for THREAD2_OK_TO_GO */      pthread_mutex_lock (&cond_mutex1);      while (queue != THREAD2_OK_TO_GO)        pthread_cond_wait (&cond1, &cond_mutex1);      pthread_mutex_unlock (&cond_mutex1);      putchar ('2');      /* notice that we're now signaling THREAD3_OK_TO_GO */      pthread_mutex_lock (&cond_mutex1);      queue = THREAD3_OK_TO_GO;      pthread_cond_broadcast (&cond1);      pthread_mutex_unlock (&cond_mutex1);    }}void*thread3_func (void *ptr){  int i;  while (1)    {      pthread_mutex_lock (&cond_mutex1);      while (queue != THREAD3_OK_TO_GO)        pthread_cond_wait (&cond1, &cond_mutex1);      pthread_mutex_unlock (&cond_mutex1);      putchar ('3');      /* signaling the first thread again */      pthread_mutex_lock (&cond_mutex1);      queue = THREAD1_OK_TO_GO;      pthread_cond_broadcast (&cond1);      pthread_mutex_unlock (&cond_mutex1);    }}