Implementing Monitors in Producer/Consumer Problem in C

193 views Asked by At
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

#define NUM_PROD 4
#define NUM_CONS 4
#define STORAGE_SPACE 3

int buffer[STORAGE_SPACE];
int last;

pthread_mutex_t mutex;
pthread_cond_t can_produce;
pthread_cond_t can_consume;


void printBuffer()
{
    int i = 0;
    for (i = 0; i < STORAGE_SPACE; i++)
    {
        printf("%d\n", buffer[i]);
    }
}


typedef struct Monitor {
//shared variable/resources
pthread_mutex_t mutex;
pthread_cond_t can_produce;
pthread_cond_t can_consume;

int buffer[STORAGE_SPACE];
int last;

}Monitor; 


void initMonitor(Monitor* monitor){
    //init shared variable & synchr objects
    monitor->last = 0;

    pthread_mutex_init(&monitor->mutex, NULL);
    pthread_cond_init(&monitor->can_produce, NULL);
    pthread_cond_init(&monitor->can_consume, NULL);

}

void *produce(Monitor* monitor, void *threadid){
    //access and manipulate shared variable/res
    long tid;
    tid = (long)threadid;
    int i, item;
    srand(time(NULL));
    for( i = 0; i < 5; i ++){
        pthread_mutex_lock(&monitor->mutex);
        while(last == STORAGE_SPACE){
            pthread_cond_wait(&monitor->can_produce, &monitor->mutex);
        }
        item = rand() % 50;
        buffer[last] = item;
        printf("prod %ld inserts item %d\n", tid, buffer[last]);
        last++;
        printBuffer();

        pthread_cond_signal(&monitor->can_consume);
        pthread_mutex_unlock(&monitor->mutex);
    }
    pthread_exit(NULL);
}

void *consume(Monitor* monitor, void *threadid){
    long tid;
    tid = (long)threadid;
    int taken;
    while(1){
        pthread_mutex_lock(&monitor->mutex);
        while(monitor->last == 0){
            pthread_cond_wait(&monitor->can_consume, &monitor->mutex);
        }
        taken = buffer[last - 1];
        buffer[last - 1] = 0;
        printf("consumer %ld took %d \n", tid, taken);
        last--;
        printBuffer();

        pthread_cond_signal(&monitor->can_produce);
        pthread_mutex_unlock(&monitor->mutex);
    }
    pthread_exit(NULL);
    return NULL;
}


int main(int argc, char *argv[])
{
    //init
    Monitor monitor; 
    initMonitor(&monitor);
    pthread_t prod[NUM_PROD], cons[NUM_CONS];
    int rc;
    long t;

    //init mutex & cond 
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&can_produce, NULL);
    pthread_cond_init(&can_consume, NULL);
   

    //creating threads
    for (t = 0; t < NUM_PROD; t++)
    {
        rc = pthread_create(&prod[t], NULL, produce, (void *)&monitor);
        if (rc)
        {
            exit(-1);
        }
    }
    for (t = 0; t < NUM_CONS; t++)
    {
        rc = pthread_create(&cons[t], NULL, consume, (void *)&monitor);
        if (rc)
        {
            exit(-1);
        }
    }

    //joining threads
    for (t = 0; t < NUM_PROD; t++)
    {
        pthread_join(prod[t], NULL);
    }
    for (t = 0; t < NUM_CONS; t++)
    {
        pthread_join(cons[t], NULL);
    }

    //destroy mutex and condition variables
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&can_produce);
    pthread_cond_destroy(&can_consume);

    pthread_exit(NULL);
    return 0;
}

Hey guys,

I would like to implement a monitor in this implementation of the producer/consumer problem.

I implemented the monitor struct as i think is correct (?) however, there is a problem when passing the functions to pthread_create and as a result I am only getting prod 0 thread being active.

I'm also not sure why the consumer function isn't being executed, but my guess is that both have to do with the fact that the produce / consume functions have (monitor, threadid) as arguments, which doesn't work with the parameters of the 3rd argument in pthread_create().

After hours of trying to google and such - I hope some one can explain where my fault(s) are.

Thanks!

0

There are 0 answers