Monday, April 28, 2014

C/C++ CODE FOR PRODUCER-CONSUMER

PRODUCER-CONSUMER PROBLEM USING SEMAPHORES


Producer-Consumer problem is a famous problem in system programming in the context of concurrency.We have implemented the code using semaphores.You can think of semaphores as flags which are responsible for permitting or denying the access to producers and consumers under certain conditions.Here we have assumed that we have an array where producers can produce and consumers can consume.A few points should be kept in mind:

  • A producer can't produce if the buffer/array is full.
  • A consumer can't consume if the buffer/array is empty.

The following code illustrates the concept:


#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#define max 20

sem_t full,empty,mutex;
pthread_t p1,c1,p2,c2,c3;
pthread_attr_t pa1,ca1,pa2,ca2,ca3;
int in=0,out=0,buffer[max],data;

//void producer();
//void consumer();
void *producer()
{
   
   printf("\nPRODUCER THREAD ENTERED THE PRODUCER FUNCTION\n");
   //sleep(10);
   
   if(in==max)
   {
     printf("THE BUFFER IS FULL");
    }
    else
    {
       sem_wait(&empty);
       sem_wait(&mutex);
       printf("ENTER THE DATA TO BE PRODUCED: ");
       scanf("%d",&data);
       buffer[in]=data;
       in++;
       sem_post(&full);
       sem_post(&mutex);
       
     }
     printf("\nPRODUCER THREAD LEAVING THE PRODUCER FUNCTION\n");
}   


void *consumer() 
{
    
   printf("\nCONSUMER THREAD ENTERED THE CONSUMER FUNCTION\n");
   sleep(10);
   
   if(out==in)
   {
     printf("THERE IS NO DATA TO BE CONSUMED");
    }
   else
   {
       sem_wait(&full);
       sem_wait(&mutex);
       data=buffer[out];
       buffer[out]=0;
       printf("CONSUMED DATA IS:%d\n",data);
       out++;
       sem_post(&empty);
       sem_post(&mutex);
    } 
    printf("\nCONSUMER THREAD LEAVING THE CONSUMER FUNCTION\n");  
    
}


int main()
{
  sem_init(&full,0,0);
  sem_init(&empty,0,max);
  sem_init(&mutex,0,1);
  pthread_attr_init(&pa1);
  pthread_attr_init(&pa2);
  pthread_attr_init(&ca1);
  pthread_attr_init(&ca2);
  pthread_attr_init(&ca3);
  pthread_create(&c1,&ca1,consumer,NULL);
  printf("\nCONSUMER THREAD CREATED\n");
  sleep(5);
  pthread_create(&c2,&ca2,consumer,NULL);
  printf("\nCONSUMER THREAD CREATED\n");
  
  pthread_create(&p1,&pa1,producer,NULL);
  printf("\nPRODUCER THREAD CREATED\n");
  sleep(5);
  pthread_create(&p2,&pa2,producer,NULL);
  printf("\nPRODUCER THREAD CREATED\n");
  sleep(5);
  sleep(5);
  pthread_create(&c3,&ca3,consumer,NULL);
  printf("\nCONSUMER THREAD CREATED\n");
  sleep(5);

  pthread_join(p1,NULL);
  pthread_join(c1,NULL);
  pthread_join(c2,NULL);
  pthread_join(c3,NULL);
  pthread_join(p2,NULL);
  return 0;
}


I have used the Linux's text editor to write the code.If you have any doubt or if you think this article can be improved,please share with us.

2 comments:

  1. #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    #define N 5 //Number of slots in buffer


    int buffer[N];
    int in = 0;
    int out = 0;


    void producer(void);
    void consumer(void);


    sem_t mutex; //Controls access to critical region 1
    sem_t empty; //Counts empty buffer slots N
    sem_t full; //Counts full buffer slots 0



    void producer(void) {

    int value;
    printf("Start producer: \n");

    sem_wait(&empty);

    sem_getvalue(&empty, &value);
    printf("\tproducer: empty = %d\n", value);

    sem_wait(&mutex);

    sem_getvalue(&mutex, &value);
    printf("\tproducer: mutex = %d\n", value);

    buffer[in] = in;
    printf("\tProducer produced: %d\n",in);

    in = (in+1)%N;

    sem_post(&mutex);
    sem_post(&full);
    sem_getvalue(&full, &value);
    printf("\tconsumer: full = %d\n", value);
    }

    void consumer(void) {

    int value;
    printf("Start consumer: \n");
    // from Figure 5.10

    sem_wait(&full);
    sem_getvalue(&full, &value);
    printf("\tconsumer: full = %d\n", value);
    sem_wait(&mutex);
    sem_getvalue(&mutex, &value);
    printf("\tconsumer: mutex = %d\n", value);
    /* remove an item from buffer to next_consumed */
    buffer[out] = out;
    printf("\tconsumer produced: %d\n",out);

    out = (out+1)%N;
    sem_post(&mutex);
    sem_post(&empty);
    sem_getvalue(&empty, &value);
    printf("\tconsumer: empty = %d\n", value);

    /* consume the item in next_consumed */

    }

    int main() {

    sem_init(&mutex, 0, 1);
    sem_init(&empty, 0, N);
    sem_init(&full, 0, 0);

    int choice;
    printf("\n1.Producer\t");
    printf("2. Consumer\t");
    printf("3. Quit\t");
    while(1)
    {
    printf("\nEnter your choice [p=1, c=2, exit=3]:\t");
    scanf("%d", &choice);
    switch(choice)
    {
    case 1:
    producer();
    continue;
    case 2:
    consumer();
    continue;
    case 3:
    break;
    }
    break;
    }
    return 0;

    }

    ReplyDelete
  2. Implementation of producer consumer in c++

    #include
    #include
    #include
    #include
    #include

    using namespace std;

    #define BUFFER_SIZE 10

    int buffer[BUFFER_SIZE];
    int index=0;

    sem_t full,empty;
    pthread_mutex_t mutex;

    void* produce(void* arg){
    while(1){
    sleep(1);
    sem_wait(&empty);
    pthread_mutex_lock(&mutex);
    int item = rand()%100;
    buffer[index++] = item;
    cout<<"Produced "<<item<<endl;
    pthread_mutex_unlock(&mutex);
    sem_post(&full);
    }
    }

    void* consume(void* arg){
    while(1){
    sleep(1);
    sem_wait(&full);
    pthread_mutex_lock(&mutex);
    int item = buffer[--index];
    cout<<"Consumed "<<item<<endl;
    pthread_mutex_unlock(&mutex);
    sem_post(&empty);
    }
    }

    int main(){
    pthread_t producer,consumer;
    sem_init(&empty,0,BUFFER_SIZE);
    sem_init(&full,0,0);
    pthread_mutex_init(&mutex,NULL);
    pthread_create(&producer,NULL,produce,NULL);
    pthread_create(&consumer,NULL,consume,NULL);
    pthread_exit(NULL);
    }

    ReplyDelete

Thanks for your valuable comment