Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Producer Consumer program using semaphores and pthreads

I have written a code for producer-consumer problem.But I am not getting the output.There is no compilation error,but warning in my program.I am confused.Trying very hard.But can't get it.Please tell me what is wrong in my program.What will be the correct program.I am getting frustrated.Please help guys. Here is the code-

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include </usr/include/semaphore.h>

#define BUFF_SIZE   5           /* total number of slots */
#define NP          3           /* total number of producers */
#define NC          3           /* total number of consumers */
#define NITERS      4           /* number of items produced/consumed */

typedef struct {
    int buf[BUFF_SIZE];   /* shared var */
    int in;               /* buf[in%BUFF_SIZE] is the first empty slot */
    int out;              /* buf[out%BUFF_SIZE] is the first full slot */
    sem_t full;           /* keep track of the number of full spots */
    sem_t empty;          /* keep track of the number of empty spots */
    sem_t mutex;          /* enforce mutual exclusion to shared data */
} sbuf_t;

sbuf_t shared;


void *Producer(void *arg) {
    int i, item, index;

    index = (int) arg;


    for (i = 0; i < NITERS; i++) {
        /* Produce item */
        item = i;

        /* Prepare to write item to buf */

        /* If there are no empty slots, wait */
        sem_wait(&shared.empty);
        /* If another thread uses the buffer, wait */
        sem_wait(&shared.mutex);
        shared.buf[shared.in] = item;
        shared.in = (shared.in+1)%BUFF_SIZE;
        printf("[P%d] Producing %d ...\n", index, item); fflush(stdout);
        /* Release the buffer */
        sem_post(&shared.mutex);
        /* Increment the number of full slots */
        sem_post(&shared.full);

        /* Interleave  producer and consumer execution */
        if (i % 2 == 1) sleep(1);
    }
    return NULL;
}

void *Consumer(void *arg) {
    int i, item, index;

    index = (int) arg;
    for (i = NITERS; i > 0; i--) {
      sem_wait(&shared.full);
      sem_wait(&shared.mutex);
      item = i;
      item = shared.buf[shared.out];
      shared.out = (shared.out + 1) % BUFF_SIZE;
      printf("[C%d] Consuming  %d ...\n", index, item); fflush(stdout);
      /* Release the buffer */
      sem_post(&shared.mutex);
      /* Increment the number of full slots */
      sem_post(&shared.empty);

      /* Interleave  producer and consumer execution */
      if (i % 2 == 1) sleep(1);
    }
    return NULL;
}

int main() {
    pthread_t idP, idC;
    int index;

    sem_init(&shared.full, 0, 0);
    sem_init(&shared.empty, 0, BUFF_SIZE);
    pthread_mutex_init(&shared.mutex, NULL);
    for (index = 0; index < NP; index++) {
       /* Create a new producer */
       pthread_create(&idP, NULL, Producer, (void*)index);
    }
    /*create a new Consumer*/
    for (index = 0;index < NC;index++) {
        pthread_create(&idC, NULL, Consumer, (void*)index);
    }
    pthread_exit(NULL);
}
like image 592
Twity 56876 Avatar asked Nov 07 '13 19:11

Twity 56876


People also ask

What is producer and consumer in semaphore?

There is a fixed size buffer and the producer produces items and enters them into the buffer. The consumer removes the items from the buffer and consumes them.

What is Producer-Consumer problem with example?

Producer-Consumer problem is a classical synchronization problem in the operating system. With the presence of more than one process and limited resources in the system the synchronization problem arises. If one resource is shared between more than one process at the same time then it can lead to data inconsistency.

How many semaphores are used in the producer and consumer problem?

The solution to the Producer-Consumer problem involves three semaphore variables. semaphore Empty : Tracks the empty space in the buffer. It is initially set to buffer_size as the whole buffer is empty at the beginning.


2 Answers

Maybe you should take the Compiler warnings more serious. Incorrect types and undefined functions are usually shown as warning...

I haven't checked the Logic of your program, but the principle should work:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include </usr/include/semaphore.h>

// for sleep
#include <unistd.h>

#define BUFF_SIZE   5           /* total number of slots */
#define NP          3           /* total number of producers */
#define NC          3           /* total number of consumers */
#define NITERS      4           /* number of items produced/consumed */

typedef struct
{
    int buf[BUFF_SIZE];   /* shared var */
    int in;               /* buf[in%BUFF_SIZE] is the first empty slot */
    int out;              /* buf[out%BUFF_SIZE] is the first full slot */
    sem_t full;           /* keep track of the number of full spots */
    sem_t empty;          /* keep track of the number of empty spots */

    // use correct type here
    pthread_mutex_t mutex;          /* enforce mutual exclusion to shared data */
} sbuf_t;

sbuf_t shared;


void *Producer(void *arg)
{
    int i, item, index;

    index = (int)arg;


    for (i=0; i < NITERS; i++)
    {

        /* Produce item */
        item = i;

        /* Prepare to write item to buf */

        /* If there are no empty slots, wait */
        sem_wait(&shared.empty);
        /* If another thread uses the buffer, wait */
        pthread_mutex_lock(&shared.mutex);
        shared.buf[shared.in] = item;
        shared.in = (shared.in+1)%BUFF_SIZE;
        printf("[P%d] Producing %d ...\n", index, item);
        fflush(stdout);
        /* Release the buffer */
        pthread_mutex_unlock(&shared.mutex);
        /* Increment the number of full slots */
        sem_post(&shared.full);

        /* Interleave  producer and consumer execution */
        if (i % 2 == 1) sleep(1);
    }
    return NULL;
}

void *Consumer(void *arg)
{
    int i, item, index;

    index = (int)arg;
    for (i=NITERS; i > 0; i--) {
        sem_wait(&shared.full);
        pthread_mutex_lock(&shared.mutex);
        item=i;
        item=shared.buf[shared.out];
        shared.out = (shared.out+1)%BUFF_SIZE;
        printf("[C%d] Consuming  %d ...\n", index, item);
        fflush(stdout);
        /* Release the buffer */
        pthread_mutex_unlock(&shared.mutex);
        /* Increment the number of full slots */
        sem_post(&shared.empty);

        /* Interleave  producer and consumer execution */
        if (i % 2 == 1) sleep(1);
    }
    return NULL;
}

int main()
{
    pthread_t idP, idC;
    int index;

    sem_init(&shared.full, 0, 0);
    sem_init(&shared.empty, 0, BUFF_SIZE);
    pthread_mutex_init(&shared.mutex, NULL);
    for (index = 0; index < NP; index++)
    {
        /* Create a new producer */
        pthread_create(&idP, NULL, Producer, (void*)index);
    }
    /*create a new Consumer*/
    for(index=0; index<NC; index++)
    {
        pthread_create(&idC, NULL, Consumer, (void*)index);
    }



    pthread_exit(NULL);
}

I hope this helps.

like image 174
user2859193 Avatar answered Nov 11 '22 23:11

user2859193


There are still compiler warnings. The correct way to get the integer value from a void pointer is:

index = *(int*)arg;

And, also to pass an integer pointer, is below:

pthread_create(&idC,NULL,Consumer,(void*)&index);

I still have some doubts as to how the Consumer or the Producer thread will receive the passed integer value since that is an address of the index variable in the for loop in the main thread. As soon as index gets incremented, the Consumer or Producer thread is affected by this increment.

like image 36
eigenfield Avatar answered Nov 11 '22 23:11

eigenfield