#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

#define ErrAbort(s,m)\
  if (s!=0){\
    fprintf(stderr,"%s: %s\n",strerror(s));\
    exit(1);\
  }

typedef struct
{
  int             count ;
  pthread_mutex_t mutex ;
} PARMS ;

void *Producer(void *p)
{
  PARMS *theParms = (PARMS *)p ;
  int    status                ;
  
  while (theParms->count > 0)
  {
    usleep(100);
    status = pthread_mutex_lock(&theParms->mutex);
    ErrAbort(status,"Producer mutex lock");
    theParms->count-- ;
    fprintf(stdout,"Producer, count = %d\n", theParms->count);
    fflush(stdout);
    status = pthread_mutex_unlock(&theParms->mutex);
    ErrAbort(status,"Producer mutex unlock");
  }
}

void *Consumer(void *p)
{
  PARMS *theParms = (PARMS *)p ;
  int    status                ;
  
  while (theParms->count > 0)
  {
    usleep(100);
    status = pthread_mutex_lock(&theParms->mutex);
    ErrAbort(status,"Consumer mutex lock");
    theParms->count-- ;
    fprintf(stdout,"Consumer, count = %d\n", theParms->count);
    fflush(stdout);
    status = pthread_mutex_unlock(&theParms->mutex);
    ErrAbort(status,"Consumer mutex unlock");
  }
}

int main()
{
  PARMS shared = { 51, PTHREAD_MUTEX_INITIALIZER };
  
  int status ;
  pthread_t threadP, threadC ;
  
  status = pthread_create(&threadP, NULL, Producer, (void *)&shared);
  ErrAbort(status,"Error creating producer");

  status = pthread_create(&threadC, NULL, Consumer, (void *)&shared);
  ErrAbort(status,"Error creating consumer");
  
  pthread_join(threadP, NULL); printf("main() producer done.\n");
  pthread_join(threadC, NULL); printf("main() consumer done.\n");
}

