hakan5 0 Newbie Poster

Good day.
Here's my code. My uncle helped me with it for days but he's now out of the country for 2 weeks. I'm looking for help to improve this project of mine with mutex and semaphores. I've never used them before and I'm a little confused. I'm running this in Ubuntu Linux. Most of the info is in the comments in my code.

I would appreciate your comments and any suggestions. Where would you guys use the semaphores/mutexes?

Regards,
HÃ¥kan

#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// I'm using g++ to compile this program in Ubuntu 9.04. I use the command ./a.out to run it.

/*
The program simulates many producers and consumers.
Producers are many and put products in a joint stack. Consumers are also many and take from this same stack.

Only the product number goes into the stack, nothing else.

Each producer makes a product number by random from 0..PRODUCTS-1 and puts into the stack. It also raises 

the appropriate element in array "production" by 1.
It also raises the production_total with 1.

Each consumer looks at the number at the top of each stack.
It raises the counter by 1 over what has been 

"consumed" by that production number by raising the element in the array "consumption". It also raises 

consumption_total by 1.

After all the threads have finished all numbers must match.
The array production must look like the array 

consumption and production_total must look like consumption_total.

The stack must start and end in 0.

So that can happen I need to synchronize producers and consumers with semaphors and mutex so they will not 

interrupt each other. How can I make the threads end? Where should I put the semaphors and mutex?
*/

#define PRODUCERS 20
#define CONSUMERS 20
#define PRODUCTS 25
#define STACKMAX 100

// Producers produce products with a product number between 0..PRODUCTS

// array production og consumption store numbers for production and consumption
// for each product.
int production[PRODUCTS];
int production_total;
int consumption[PRODUCTS];
int consumption_total;

int stacksize;  // stack can be 0..STACKSIZE-1, I need to use semaphore to watch out for highs and lows...
int stack[STACKMAX];

// This is how I learnt how to create a semaphore
sem_t semaphore;

//This is how a semaphore is usually used:
//sem_wait(&semaphore);
//sem_post(&semaphore);


//This is how I learnt how to create a mutex - could need more
pthread_mutex_t mutex;
//This is how they're suppoes to be used
//pthread_mutex_lock(&mutex);
//pthread_mutex_unlock(&mutex);

#define True 1
#define False 0

// If quitting = True then we're stopping and all threads should exit
int quitting;


void* producer(void *arg)
{
    int product_number;

    printf("I'm a producer\n");

    return NULL;  // This needs to be removed so the code will run

    // I need to change this code!  Here I need at least one semaphore and probably one mutex.
    // The 

if.then.else used here is not the most suitable solution. 
    while(!quitting)
    {
         if(stacksize<STACKMAX)
         {
              product_number=rand()%PRODUCTS;  // Some number on between 0..PRODUCTS
              // Put on stack
              stack[stacksize++]=product_number;

              // and record it..
              production[product_number]++;
              production_total++;
         }
         else
	 {
              printf("The stack is full!\n");
         }
    }
    return NULL;
}

void* consumer(void *arg)
{
    int product_number;

    printf("I'm a consumer!\n");

    return NULL;  // This return should delete

    // I need to change this code!  Here I need at least one semaphore and probably one mutex.
    // The 

if.then.else used here is not the most suitable solution. 

    while(!quitting)
    {
	 if(stacksize>0)
         {
              product_number=stack[--stacksize];
              consumption[product_number]++;
              consumption_total++;
         }
         else
	 {
              printf("The stack is empty!\n");
         }

    }
    return NULL;
}


int main(int argc, char **argv)
{
    pthread_t consumer_threads[CONSUMERS];
    pthread_t producer_threads[PRODUCERS];


    // Initialize the semaphore with a value of 1.
    // Note the second argument: passing zero denotes
    // that the semaphore is shared between threads (and
    // not processes).
    if(sem_init(&semaphore, 0, 1))
    {
        printf("Could not initialize a semaphore\n");
        return -1;
    }

    // Initialize the mutex
    if(pthread_mutex_init(&mutex, NULL))
    {
        printf("Unable to initialize a mutex\n");
        return -1;
    }

    // Null random generator
    srand(0);

    // Null all counters
    stacksize=0;
    consumption_total=0;
    production_total=0;
    for(int i=0;i<PRODUCTS;i++)
    {
         consumption[i]=0;
         production[i]=0;
    }

    // Consumers can look at this global variable to see if producers have stopped producing 	 // and it's 

safe to quit
    quitting=False;

    // Print initial values
    printf("stacksize (should be 0) = %i\n",stacksize);
    printf("production_total = %i\n",production_total);
    printf("consumption_total = %i (needs to match production)\n",consumption_total);

    printf("Production array broken down:\n");
    for(int i=0;i<PRODUCTS;i++)
    {
         printf("%i ",production[i]);
    }
    printf("\n");

    printf("Consumption array broken down (needs to match production array):\n");
    for(int i=0;i<PRODUCTS;i++)
    {
         printf("%i ",consumption[i]);
    }
    printf("\n");


    // Start the producer
    
    for(int i = 0; i < PRODUCERS; ++i)
    {
        if(pthread_create(&producer_threads[i], NULL, &producer, NULL))
        {
            printf("Could not create thread %d\n", i);
            return -1;
        }
    }

    // Start the consumer

    int thread_count=0;

    for(int i = 0; i < CONSUMERS; ++i)
    {
        if(pthread_create(&consumer_threads[i], NULL, &consumer, NULL))
        {
            printf("Could not create thread %d\n", i);
            return -1;
        }
    }

    // The main program sleeps for a while
    // then puts the global variable qutting = True , by that all consumers and producers 
    //should stop 

producing.
    sleep(3);
    quitting=True; 
    printf("Now the main program wants to quit...\n");


    for(int i = 0; i < CONSUMERS; ++i)
    {
        if(pthread_join(consumer_threads[i], NULL))
        {
            printf("Could not join thread %d\n", i);
            return -1;
        }
    }

    for(int i = 0; i < PRODUCERS; ++i)
    {
        if(pthread_join(producer_threads[i], NULL))
        {
            printf("Could not join thread %d\n", i);
            return -1;
        }
    }

    printf("All threads are dead\n");

    sem_destroy(&semaphore);
    pthread_mutex_destroy(&mutex);

    printf("All over.. now everything should match\n");
    printf("stacksize (should be 0) = %i\n",stacksize);
    printf("production_total = %i\n",production_total);
    printf("consumption_total = %i (needs to match production)\n",consumption_total);

    printf("Production array broken down:\n");
    for(int i=0;i<PRODUCTS;i++)
    {
         printf("%i ",production[i]);
    }
    printf("\n");

    printf("Consumption array broken down (needs to match production array):\n");
    for(int i=0;i<PRODUCTS;i++)
    {
         printf("%i ",consumption[i]);
    }
    printf("\n");

    return 0;
}