0

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:

  1. The car always rides with exactly C passengers;

  2. No passengers will jump off the car while the car is running;

  3. 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;
}
Brian Ha
  • 9
  • 3
  • 1
    "using semaphores only" Hmm, that sounds strange. – Support Ukraine Apr 25 '18 at 06:50
  • 1
    You haven't posted the code that call these functions so it's difficult to help – Support Ukraine Apr 25 '18 at 06:53
  • @4386427 Updated it a little bit. – Brian Ha Apr 25 '18 at 13:45
  • 1
    You seem to using `pthread_cond_wait` incorrectly. Read this: https://stackoverflow.com/a/13122435/4386427 – Support Ukraine Apr 25 '18 at 14:37
  • it is a poor programming practice to `#include` header files in a header file that does not use the contents of the included header file. I.E. move the `#include` statements to the main C file. – user3629249 Apr 25 '18 at 16:38
  • the car thread function will NEVER exit This is an error – user3629249 Apr 25 '18 at 16:45
  • the only way to not have the car load function never hang is to have the capacity of the car set to 1 – user3629249 Apr 25 '18 at 16:46
  • regarding: `pthread_create(&passengersThreads[i], &threadAttributes, (void*) passengerThreadFunction, (void*)i);` 1( always check the returned value from C library functions to assure the operation was successful 2) the variable `i` is constantly changing so is not a reliable item to pass. 3) the size of a `int` and the size of a `pointer (especially on 64 bit architectures) are not the same so casting a `int` to a pointer is not reliable – user3629249 Apr 25 '18 at 16:50
  • mutex's should be used to protect data that can change asynchronously. Not on the state of some condition. – user3629249 Apr 25 '18 at 17:01

0 Answers0