The Famous Roller Coaster Problem. Suppose there are n passengers and one roller coaster car. The passengers repeatedly wait to take rides on the car. The car has a capacity of C seats, C < n, but the cheapskate owners won't let the car leave the station until it is full. Write a program to simulate a solution to this problem. Each passenger MUST be a thread that waits to take a ride, waits until the ride completes, disembarks from the ride and exits.
The car should be a thread that waits until C passengers enter the car for a ride, then goes around the track for some fixed amount of time (some fixed sleep time), then lets the passengers disembark. It does this until there are no more passengers wanting rides.
Your main() thread will perform a pthread_join() on the car thread. When there are no more waiting passenger threads, the car thread exits and thus the main() thread will print something informative and exit.
So, suppose the car and each passenger are represented by separate threads. How would you write a program that can simulate this system and fulfill the following requirements:
The car always rides with exactly C passengers;
No passengers will jump off the car while the car is running;
No passengers will jump on the car while the car is running;
The threads are to synchronize by means of a "monitor" (remember, it uses a mutex and a conditional variable to guarantee mutual exclusion) which has three operations: takeRide, loadCustomers, and unloadCustomers. The first operation is called by passengers; a call does not return until the passenger has taken a ride and is ready to leave. The last two operations are called by the car thread. You may add anything else to help your design work.
My problem: These are the functions to be passed into the threads. takeRide
is passed into the passenger threads, load and unload are passed into the car thread. First, there are combinations of passengers and car capacity that will not work. For example, a capacity of 2 for the car and 7 passengers. This will be stuck on the last passenger. Secondly, the unboarding doesn't work properly. I don't see the "passenger x left car." How do I fix this issue of it not working for every passenger/capacity combination? Do I need another mutex
? Also, why does it just stop running randomly like the sample output below? And how come carUnload doesn't work properly?
Sample deadlock output: capacity=2, passengers=6
Passenger 5 is waiting for car.
Passenger 4 is waiting for car.
Passenger 3 is waiting for car.
Passenger 2 is waiting for car.
Passenger 1 is waiting for car.
Passenger 0 is waiting for car.
Car is waiting for passengers.
Passenger 4 will take ride in the car
Passenger 3 will take ride in the car
Passenger 2 is waiting for car.
Passenger 1 is waiting for car.
Passenger 5 is waiting for car.
Passenger 0 is waiting for car.
.h
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int cap, numPass;
int passengersInCar;
bool carIsWaiting; //true if car is waiting for passengers
pthread_mutex_t rollerCoasterLock;
pthread_cond_t carLoad;
pthread_cond_t carUnload;
pthread_cond_t carFull;
.C
void takeRide(const int passenger_id);
void load();
void unload();
void takeRide(const int passenger_id){
pthread_mutex_lock(&rollerCoasterLock);
while(!carIsWaiting || passengersInCar==cap){
printf("Passenger %d is waiting for car.\n", passenger_id);
pthread_cond_wait(&carLoad, &rollerCoasterLock);
}
// numPass--;
passengersInCar++;
printf("Passenger %d will take ride in the car\n", passenger_id);
if (passengersInCar == cap){
pthread_cond_broadcast(&carFull);
// passengersInCar=0;
}
pthread_cond_wait(&carFull, &rollerCoasterLock);
pthread_cond_wait(&carUnload, &rollerCoasterLock);
printf("Passenger %d left car.\n", passenger_id);
pthread_mutex_unlock(&rollerCoasterLock);
pthread_exit(0);
}
void load(){
pthread_mutex_lock(&rollerCoasterLock);
// if(numPass==0)
// pthread_exit(NULL);
while(passengersInCar>0){
pthread_cond_wait(&carUnload, &rollerCoasterLock);
}
carIsWaiting = true;
pthread_cond_broadcast(&carLoad);
printf("Car is waiting for passengers.\n");
pthread_cond_wait(&carFull, &rollerCoasterLock);
carIsWaiting = false;
pthread_cond_broadcast(&carFull);
printf("Car is full. Going around...\n" );
pthread_mutex_unlock(&rollerCoasterLock);
}
void unload(){
pthread_mutex_lock(&rollerCoasterLock);
pthread_cond_broadcast(&carUnload);
puts("unloading...");
passengersInCar=0;
pthread_mutex_unlock(&rollerCoasterLock);
// pthread_exit(0);
}
Main
#include <pthread.h>
#include <unistd.h>
#include "rollerCoaster.h"
void* carThreadFunction();
void* passengerThreadFunction(int passenger_id);
void testRollerCoasterOneCar(int carCapacity, int numPassengers);
int cap, numPass;
pthread_attr_t threadAttributes;
int main(int argc, char *argv[]) {
passengersInCar = 0;
carIsWaiting = false;
pthread_mutex_init(&rollerCoasterLock, NULL);
pthread_cond_init(&carLoad, NULL);
pthread_cond_init(&carUnload, NULL);
pthread_cond_init(&carFull, NULL);
//check command line args
if (argc != 3){
puts("Please enter (car-capacity-num) and (num-of-passengers).\n");
exit(0);
} else {
cap = atoi(argv[1]);
numPass = atoi(argv[2]);
}
pthread_attr_init(&threadAttributes);
pthread_attr_setscope(&threadAttributes, PTHREAD_SCOPE_SYSTEM);
testRollerCoasterOneCar(cap, numPass);
pthread_join(carThread, NULL);
puts("done");
return 0;
}
void testRollerCoasterOneCar(int carCapacity, int numPassengers) {
// rollerCoasterOneCar = new RollerCoasterOneCar(carCapacity);
pthread_t carThread;
pthread_create(&carThread, &threadAttributes, (void*) carThreadFunction, (void*) NULL);
pthread_t passengersThreads[numPassengers];
for (int i = 0; i < numPassengers; i++) {
pthread_create(&passengersThreads[i], &threadAttributes, (void*) passengerThreadFunction, (void*)i);
}
}
void* carThreadFunction(){
while(true){
load();
usleep(100000);
unload();
}
return NULL;
}
void* passengerThreadFunction(int passenger_id){
while(true){
takeRide(passenger_id);
}
return NULL;
}