Reputation: 2329
I am trying to create a simple bar program where a certain amount of customers can be inside the bar at the same time. And every time a customer asks for a beer, then the bartender should server the customer a beer.
For some reason in my program, the bar tender serves the customer after he/she leaves the bar
How can I fix this? Any suggestions?
Here is my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> //for declaration of exit()
#include <semaphore.h> //to use semaphores
pthread_mutex_t serve = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
sem_t OktoEnter;
int cid = 0;
void EnterBar();
void OrderStart();
void ServeStart();
void ServeDone();
void OrderDone();
void DrinkBeer();
void LeaveBar();
void* Bartender(void *arg)
{
ServeStart();
ServeDone();
}
void* Customer(void* id)
{
cid =(int)id;
EnterBar();
LeaveBar();
}
void EnterBar(){
printf("Customer %d enters the bar.\n", cid);
int cups;
pthread_t order;
for(cups=0;cups<(cid%3+1);cups++){
pthread_mutex_lock(&serve);
OrderStart();
OrderDone();
DrinkBeer();
pthread_mutex_unlock(&serve);
}
//decrease semaphore
}
void OrderStart(){
pthread_t order;
printf("Customer %d asks for beer.\n", cid);
int rc = pthread_create(&order, NULL, Bartender, NULL);
}
void OrderDone(){
printf("Customer %d gets the beer.\n", cid);
}
void DrinkBeer(){
printf("Customer %d drinks the beer.\n", cid);
}
void LeaveBar(){
printf("Customer %d leaves the bar.\n", cid);
//increase semaphore
}
void ServeStart(){
printf("Bartender starts to serve customer %d.\n", cid);
}
void ServeDone(){
printf("Bartender is done serving customer %d.\n", cid);
}
int main (int argc, char *argv[])
{
int t;
long rc;
int num_customers = atoi(argv[1]); //number of customers
int capacity = atoi(argv[2]); //bar capacity
if(num_customers > 0 && capacity > 0){
pthread_t threads[num_customers];
if(random() > RAND_MAX / 2)
usleep(1);
//rc = sem_init(&sem1,0,capacity);
rc = pthread_barrier_init(&barrier1, NULL, num_customers);
for(t=0; t< num_customers; t++){
printf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, Customer, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %ld\n", rc);
exit(-1);
}
}
}
else{
printf("ERROR: Both parameters should be a valid positive numbers.");
exit(-1);
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
I worked all around changing the functions but it does not work properly.
Upvotes: 1
Views: 280
Reputation: 26
First, this is a great little project in understanding threads and how life is multi-threaded.
There are problems with the above scenarios. First off, neither of you are keeping track of how many customers are in the bar from your EnterBar() and LeaveBar() functions. In these functions, you will need to keep track of the current bar count. Once the bar is full, you must lock the door so no other customers can enter. Then when a customer leaves the bar, they must unlock the door so at least one more customer can enter. Also, given the complete problem scenario, you should only create one bartender (i.e. one bartender thread) and syncronize with him using pthread_cond_wait/pthread_cond_signal to pour the beer once a customer asks for it. You can't just keep killing off and recreating the bartender for each drink to be poured, and remember only one customer can ask for a beer at a time. This should all be done with pthread_mutex_lock/unlock's.
Upvotes: 1
Reputation: 27542
To be honest it is not clear if you originally had a clear idea of where you were going with this to begin with or just got so lost in the weeds you started throwing things against the wall to see what would stick. Sorry for the mixed metaphors.
You had a bunch of small errors (e.g. sometimes cid was a param, sometimes it was a global shared by all threads) and a bunch of unnecessary stuff I assume was detritus from experimenting.
I stripped this down a very basic threaded program and I'll leave it at that since I really don't understand where exactly you want to take it. Get the simple stuff working first, layer on the complexity later. Good luck.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void EnterBar();
void OrderStart();
void ServeStart();
void ServeDone();
void OrderDone();
void DrinkBeer();
void LeaveBar();
void Bartender(int cid)
{
ServeStart(cid);
ServeDone(cid);
}
void* Customer(void* id)
{
int cid = (int) id;
EnterBar(cid);
LeaveBar(cid);
}
void EnterBar(int cid)
{
printf("Customer %d enters the bar.\n", cid);
int cups;
pthread_t order;
OrderStart(cid);
OrderDone(cid);
DrinkBeer(cid);
}
void OrderStart(int cid)
{
printf("Customer %d asks for beer.\n", cid);
Bartender(cid);
}
void OrderDone(int cid)
{
printf("Customer %d gets the beer.\n", cid);
}
void DrinkBeer(int cid)
{
printf("Customer %d drinks the beer.\n", cid);
}
void LeaveBar(int cid)
{
printf("Customer %d leaves the bar.\n", cid);
}
void ServeStart(int cid)
{
printf("Bartender starts to serve customer %d.\n", cid);
}
void ServeDone(int cid)
{
printf("Bartender is done serving customer %d.\n", cid);
}
int main (int argc, char *argv[])
{
int t;
long rc;
if (argc < 3)
{
printf("use the parameters\n");
exit(1);
}
int num_customers = atoi(argv[1]); //number of customers
int capacity = atoi(argv[2]); //bar capacity
if (num_customers <= 0 || capacity <= 0)
{
printf("ERROR: Both parameters should be a valid positive numbers.");
exit(1);
}
pthread_t threads[num_customers];
for (t = 0; t < num_customers; t++)
{
printf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, Customer, (void* )t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %ld\n", rc);
exit(1);
}
}
for (t = 0; t < num_customers; t++)
pthread_join(threads[t], NULL);
pthread_exit(NULL);
}
Upvotes: 3