Øvelse+6+-+Thread+Synchronization+II+-+aka.+Park-a-lot-9000

=Exercise 1 Implement Park-a-Lot 2000=

Exercise 1.1 First step
Implement the PLCS and verify that it works with a single car that enters the parking lot, waits there for some time and exits the parking lot again.

code format="cpp" /* The problem with this code is, at the only works with one car at a time. When a car comes to the gate we lock a mutex and set carWaitingEntry = true, now we send a signal to Entry and we go to another thread that handels the funktion garageDoorEntryController, the function set garageDoorEntryController = true, now we again send a signal to Entry, then we come back to the frist thread there handels carEntry and set carWaitingEntry = false and again we signal to the thread that handels garageDoorEntryController and set garageDoorOpenEntry = false.

The threads there handels carExit and carWaitingExit does the same as the first.

In this exercise we have made a two-way synchronization, where all waits are matched with signals.


 * 1) include
 * 2) include 
 * 3) include 

pthread_mutex_t mEntry = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mExit = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t Entry = PTHREAD_COND_INITIALIZER; pthread_cond_t Exit = PTHREAD_COND_INITIALIZER;

bool carWaitingEntry = false; bool carWaitingExit = false; bool garageDoorOpenEntry = false; bool garageDoorOpenExit = false;

void *carExit(void*) {   std::cout <<"The car is at the end!\n"; pthread_mutex_lock( &mExit ); carWaitingExit = true; pthread_cond_signal(&Exit); while (!garageDoorOpenExit) {       pthread_cond_wait(&Exit, &mExit); }

std::cout << "The car has run out!\n"; carWaitingExit = false; pthread_cond_signal(&Exit); pthread_mutex_unlock(&mExit); }

void *garageDoorExitController(void*) {   pthread_mutex_lock( &mExit ); while (!carWaitingExit) {       pthread_cond_wait(&Exit, &mExit); }   std::cout << "Exit door is open!\n"; garageDoorOpenExit = true; pthread_cond_signal(&Exit); while (carWaitingExit) {       pthread_cond_wait(&Exit, &mExit); }   std::cout << "The gate closes!\n"; garageDoorOpenExit = false; pthread_mutex_unlock(&mExit); }

void *carEntry(void*) {   std::cout << "The car is waiting at the garage!\n"; pthread_mutex_lock( &mEntry ); carWaitingEntry = true; pthread_cond_signal(&Entry); while (!garageDoorOpenEntry) {       pthread_cond_wait(&Entry, &mEntry); }

std::cout << "The car is driven into the garage!\n"; carWaitingEntry = false; pthread_cond_signal(&Entry); pthread_mutex_unlock(&mEntry); }

void *garageDoorEntryController(void*) {   pthread_mutex_lock( &mEntry ); while (!carWaitingEntry) {       pthread_cond_wait(&Entry, &mEntry); }   std::cout << "The entrygate is open!\n"; garageDoorOpenEntry = true; pthread_cond_signal(&Entry); while (carWaitingEntry) {       pthread_cond_wait(&Entry, &mEntry); }   std::cout << "The entrygate closes!\n"; garageDoorOpenEntry = false; pthread_mutex_unlock(&mEntry); }

int main (int argc, char const* argv[]) {     pthread_t thread;

pthread_create(&thread, NULL, carEntry, NULL); pthread_create(&thread, NULL, garageDoorEntryController, NULL);

sleep(3);

pthread_create(&thread, NULL, carExit, NULL); pthread_create(&thread, NULL, garageDoorExitController, NULL);

for {       sleep(100); } } code

Exercise 1.2 The grandiose test
Repeat the above test this time with multiple cars, where each car is being represented by a single thread. Furthermore every car should wait a different amount of time in the parking lot before exiting. Verify that all cars are able to enter and exit as would be expected.

code format="cpp" /* Now the code works with NAX_NO_OF_CAR_THREADS. But there is still no maximum capacity for the parkinglot.

Each car thread waits a random time between 1 and 5 seconds before wanting to enter the car park, and also before wanting to exit.

When a car comes to the gate we lock a mutex and set carWaitingEntry = true, now we send a signal to Entry and we go to another thread that handles the function garageDoorEntryController, the function sets garageDoorEntryController = true, now we again send a signal to Entry, then we come back to the frist thread which handles carEntry and sets carWaitingEntry = false and again we signal to the thread that handles garageDoorEntryController and sets garageDoorOpenEntry = false.

The threads there handles carExit and carWaitingExit does the same as the first.

In this exercise we have made a two-way synchronization, where all waits are matched with signals.




 * 1) define MAX_NO_OF_CAR_THREADS 5 //number of car threads to start - THIS IS NOT THE PARKING CAPACITY! - it isn't implemented.. yet.


 * 1) include
 * 2) include 
 * 3) include 


 * 1) include  //for the random delay.

pthread_mutex_t mEntry = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mExit = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t Entry = PTHREAD_COND_INITIALIZER; pthread_cond_t Exit = PTHREAD_COND_INITIALIZER;

bool carWaitingEntry = false; bool carWaitingExit = false; bool garageDoorOpenEntry = false; bool garageDoorOpenExit = false;

void *car(void *car_number) { int random_int; while(1) {   std::cout << "\nCar " << (int)car_number << "  wants parking\n"; pthread_mutex_lock( &mEntry ); carWaitingEntry = true; pthread_cond_signal(&Entry); while (!garageDoorOpenEntry) {       pthread_cond_wait(&Entry, &mEntry); }

std::cout << "Car " << (int)car_number << " is now in\n"; carWaitingEntry = false; pthread_cond_signal(&Entry); pthread_mutex_unlock(&mEntry);

//RANDOM WAIT.

random_int = (rand % 5) + 1; //random number between 0 and 5

//debug: /*   std::cout << "\n\nFirst Random: "; std::cout << random_int; std::cout << "\n\n"; sleep(random_int);

std::cout << "Car " << (int)car_number << " wants to exit\n"; pthread_mutex_lock( &mExit ); carWaitingExit = true; pthread_cond_signal(&Exit); while (!garageDoorOpenExit) {       pthread_cond_wait(&Exit, &mExit); }

std::cout << "Car " << (int)car_number << " is now gone\n"; carWaitingExit = false; pthread_cond_signal(&Exit); pthread_mutex_unlock(&mExit);

//RANDOM WAIT.

random_int = (rand % 5) + 1;

//debug: /*   std::cout << "\n\nSecond Random: "; std::cout << random_int; std::cout << "\n\n"; sleep(random_int); } }

void *garageDoorExitController(void*) { while(1) {   pthread_mutex_lock( &mExit ); while (!carWaitingExit) {       pthread_cond_wait(&Exit, &mExit); }   std::cout << "Exit door ajar!\n\n"; garageDoorOpenExit = true; pthread_cond_signal(&Exit); while (carWaitingExit) {       pthread_cond_wait(&Exit, &mExit); }   std::cout << "The exit gate is closing\n\n"; garageDoorOpenExit = false; pthread_mutex_unlock(&mExit); } }

void *carEntry(void*) { while(1) {

std::cout << "A car is waiting to enter!\n"; pthread_mutex_lock( &mEntry ); carWaitingEntry = true; pthread_cond_signal(&Entry); while (!garageDoorOpenEntry) {       pthread_cond_wait(&Entry, &mEntry); }

std::cout << "The car has come in\n\n"; carWaitingEntry = false; pthread_cond_signal(&Entry); pthread_mutex_unlock(&mEntry); } }

void *garageDoorEntryController(void*) { while(1) {

pthread_mutex_lock( &mEntry ); while (!carWaitingEntry) {       pthread_cond_wait(&Entry, &mEntry); }   std::cout << "The entrygate is open\n"; garageDoorOpenEntry = true; pthread_cond_signal(&Entry); while (carWaitingEntry) {       pthread_cond_wait(&Entry, &mEntry); }   std::cout << "Entrygate closing!\n"; garageDoorOpenEntry = false; pthread_mutex_unlock(&mEntry); } }

int main (int argc, char const* argv[]) {

srand(time(NULL)); //seed the random number generator.

pthread_t thread;

pthread_create(&thread, NULL, garageDoorEntryController, NULL);

pthread_create(&thread, NULL, garageDoorExitController, NULL);

for(int i = 1; i < MAX_NO_OF_CAR_THREADS+1; i++) {     pthread_create(&thread, NULL, car, (void*)i); //create car threads with incrementing IDs }

for {   } } code The output of the above is a follows: =[optional] - Exercise 2 Extending PCLS, now with a limit on the number of cars= We now add an additional requirement to the PLCS:
 * The entry guard must ensure that entry is not granted to a car if the parking lot is full. In that case cars wanting to enter must wait.

Extend your PLCS to handle this situation and verify that it actually does as you expect. Remember to test the scenario where a car leaves a full parking lot, enabling a waiting car to enter.