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;
}