// Prototypes void* customer(void* num); void* barber(void* num); // Global Data sem_t BtoC; sem_t CtoB; sem_t haircutDone; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int waitingCustomersNo = 0; int numChairs = 0; int numCustomers = 0; int numBarbers = 0; int main(int argc, char** argv) { pthread_t barbers_tid[100]; pthread_t customers_tid[100]; if(argc != 4) { printf("Usage: %s #customers #chairs #barbers\n", argv[0]); return -1; } numCustomers = atoi(argv[1]); numChairs = atoi(argv[2]); numBarbers = atoi(argv[3]); //Initialize semaphores: sem_init(&BtoC, 0, 0); sem_init(&CtoB, 0, 0); sem_init(&haircutDone, 0, 0); for(int i = 1; i <= numBarbers; i++) { if(pthread_create(&barbers_tid[i-1], NULL, barber, (void*) i) == 0) { //printf("Created barber #%d.\n",i); } else { printf("Failed to create barber #%d! So only %d barbers will be used.\n",i, i-1); numBarbers = i-1; break; } } for(int i = 1; i <= numCustomers; i++) { if(pthread_create(&customers_tid[i-1], NULL, customer, (void*) i) == 0) { sleep(1); //printf("Created customer #%d.\n",i); } else { printf("Failed to create customer #%d! So only %d customers will be used.\n",i, i-1); numCustomers = i-1; break; } } for(int i = 0; i < numBarbers; i++) { pthread_join(barbers_tid[i], NULL); } for(int i = 0; i < numCustomers; i++) { pthread_join(customers_tid[i], NULL); } return 0; } void* customer(void* number) { int myNum = (int) number; pthread_mutex_lock(&mutex); printf("Customer #%d has arrived. \t\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); fflush(stdin); if(numChairs > waitingCustomersNo) { waitingCustomersNo++; printf("Customer #%d took a seat.\t\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); //pthread_mutex_unlock(&mutex); sem_post(&CtoB); pthread_mutex_unlock(&mutex); printf("CUSTOMER #%d is calling wait(BtoC)\n", myNum); sem_wait(&BtoC); printf("Customer #%d is now receiving a haircut.\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); sem_wait(&haircutDone); //printf("Customer #%d's haircut is done.\t\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); } else { printf("Customer #%d notices there are no open seats.\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); pthread_mutex_unlock(&mutex); } printf("Customer #%d left the barber shop.\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); pthread_exit(NULL); } void* barber(void* number) { int myNum = (int) number; printf("Barber #%d has arrived.\t\t\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); while(1) { sem_wait(&CtoB); pthread_mutex_lock(&mutex); //sleep(10); waitingCustomersNo--; if(waitingCustomersNo < 0) { printf("WTF?!?!?!?!\n"); //should never reach this point! //pthread_mutex_unlock(&mutex); } printf("Barber #%d took the next waiting customer.\t\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); sem_post(&BtoC); pthread_mutex_unlock(&mutex); sleep(2); sem_post(&haircutDone); printf("Barber #%d is done with the haircut.\t#customers=%d seats_left=%d\n", myNum, waitingCustomersNo, numChairs-waitingCustomersNo); } pthread_exit(NULL); }