Pages

Tuesday, October 23, 2012

ISU - Exercise 6 - Thread Synchronization II Parking Lot Control System


Goal

To give you some routine in mapping real-world problems to multithreaded programmed solutions

1. Implement Park-a-Lot 2000 (60%)

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.

Question: Which statement is valid and why?

1. One conditional variable used with multiple mutexes.
2. Multiple conditional variables used in a single mutex.

The second statement is true because we are dealing with multiple threads. By using multiple conditional variables we can control which thread receive what signal.

1.1 First step - Solution


#include <pthread.h>

#include <iostream>
using namespace std;

int carWaitingIn=0;
int carWaitingOut=0;
int numberOfcars=0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t carCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t entryCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t exitCond = PTHREAD_COND_INITIALIZER;

void *entry(void *arg)
{
  while(true)
  {
    pthread_mutex_lock(&mutex);
       while(!carWaitingIn)
        {pthread_cond_wait(&entryCond,&mutex);} 
       
       pthread_cond_signal(&carCond); 
       --carWaitingIn;
       ++numberOfcars;
    pthread_mutex_unlock(&mutex);
   }
   return (void *)0;
}

void *exit(void *arg)
{
  while(true)
  {
    pthread_mutex_lock(&mutex);
      while(!carWaitingOut)
       {pthread_cond_wait(&exitCond,&mutex);}
      --carWaitingOut;
      --numberOfcars;
      pthread_cond_signal(&carCond);
    pthread_mutex_unlock(&mutex);
  }
   return (void *)0;
}

void *car(void *arg)
{
  while(true)
  {
   pthread_mutex_lock(&mutex);
     ++carWaitingIn;
     pthread_cond_signal(&entryCond);
     while(carWaitingIn)
      {pthread_cond_wait(&carCond,&mutex);}
     cout << "Number of cars in parking lot: " << numberOfcars << endl;
   pthread_mutex_unlock(&mutex);

   sleep(5);

   pthread_mutex_lock(&mutex);
     ++carWaitingOut;
     pthread_cond_signal(&exitCond);
     while(carWaitingOut)
      {pthread_cond_wait(&carCond,&mutex);}
     cout << "Number of cars in parking lot: " << numberOfcars << endl;
   pthread_mutex_unlock(&mutex);
   
   sleep(5);
  }
   return (void *)0;
}

int main(void)
{
                  void *exit_status;
                  int s;

                  cout<<"Creating threads"<<endl;
                  pthread_t carThread;
                  pthread_t entryThread;
                  pthread_t exitThread;
                  int value = 0;

                  s=pthread_create(&entryThread, NULL, entry, &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  s=pthread_create(&carThread, NULL, car, &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}


                  s=pthread_create(&exitThread, NULL, exit , &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  pthread_join(carThread, &exit_status);
                  pthread_join(entryThread, &exit_status);
                  pthread_join(exitThread, &exit_status);
                  cout<<"Threads terminated"<<endl;
                  return 0;
}


1.2 The grandiose test

Repeat the above test this time with multiple cars. Furthermore every car should wait a different amount of time in the parking lot before exiting. In this scenario the car park does not have an upper bound on the number of cars it has space for.

Verify that all cars are able to enter and exit as would be expected.

Consider and argue when and why you are to use pthread_cond_broadcast(), also explain what it does.


1.2 The grandiose test - Solution

#include <pthread.h>
#include <iostream>
#include <stdlib.h>
using namespace std;

int carWaitingIn=0;
int carWaitingOut=0;
int numberOfcars=0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t carCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t entryCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t exitCond = PTHREAD_COND_INITIALIZER;

void *entry(void *arg)
{
                  while(true)         
                  {
                                    pthread_mutex_lock(&mutex);
                                                      while(!carWaitingIn)
                                                      {pthread_cond_wait(&entryCond,&mutex);}
                                                      //cout << "test1" << endl;
                                                      pthread_cond_signal(&carCond);
                                                      //cout << "test2" << endl;
                                                      --carWaitingIn;
                                                      ++numberOfcars;
                                    pthread_mutex_unlock(&mutex);
                  }
                  return (void *)0;
}

void *exit(void *arg)
{
                  while(true)
                  {
                                    pthread_mutex_lock(&mutex);
                                                      while(!carWaitingOut)
                                                      {pthread_cond_wait(&exitCond,&mutex);}
                                                      --carWaitingOut;
                                                      --numberOfcars;
                                                      pthread_cond_signal(&carCond);
                                    pthread_mutex_unlock(&mutex);
                  }
                  return (void *)0;
}

void *car(void *arg)
{
                  int carNumber = (int)arg;

                  while(true)
                  {
                  pthread_mutex_lock(&mutex);
                                    ++carWaitingIn;
                                    cout << "Car no. " << carNumber << " waiting at entry" << endl;
                                    pthread_cond_signal(&entryCond);
                                    while(carWaitingIn)
                                    {pthread_cond_wait(&carCond,&mutex);}
                                    cout << "Car no. " << carNumber<< " at parking lot" << endl;
                  pthread_mutex_unlock(&mutex);

                  sleep(rand() % 5 + 3);

                  pthread_mutex_lock(&mutex);
                                    ++carWaitingOut;
                                    cout << "Car no. " << carNumber << " waiting at exit" << endl;
                                    pthread_cond_signal(&exitCond);
                                    while(carWaitingOut)
                                    {pthread_cond_wait(&carCond,&mutex);}

                  pthread_mutex_unlock(&mutex);
                  sleep(5);
                  }
                  return (void *)0;
}

int main(void)
{
                  void *exit_status;
                  int s;

                  cout<<"Creating threads"<<endl;
                  pthread_t carThread[5];
                  pthread_t entryThread;
                  pthread_t exitThread;
                  int value = 0;

                  s=pthread_create(&entryThread, NULL, entry, &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  for(int i=0;i<5;i++)
                  {
                                    s=pthread_create(&carThread[i], NULL, car, (void *)i);
                                    if(s != 0)
                                    {cout<<"Thread create error"<<endl;}
                  }



                  s=pthread_create(&exitThread, NULL, exit , &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  for(int i=0;i<5;i++)
                  {
                                    pthread_join(carThread[i], &exit_status);
                  }
                  pthread_join(entryThread, &exit_status);
                  pthread_join(exitThread, &exit_status);
                  cout<<"Threads terminated"<<endl;
                  return 0;
}


Console Output:















2. Extending PCLS, now with a limit on the number of cars (40%)


#include <pthread.h>
#include <iostream>
#include <stdlib.h>
using namespace std;

int carWaitingIn=0;
int carWaitingOut=0;
int numberOfcars=0;
int maxCars=5;
bool port = false;
bool sensor = false;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t carCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t entryCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t exitCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t freeSpace = PTHREAD_COND_INITIALIZER;
static pthread_cond_t carEntered = PTHREAD_COND_INITIALIZER;

void *entry(void *arg)
{
                  while(true)
                  {
                                    pthread_mutex_lock(&mutex);

                                                      while(!carWaitingIn)
                                                      {pthread_cond_wait(&entryCond,&mutex);}

                                                      port = true;
                                                      pthread_cond_signal(&carCond);

                                                      while(sensor == false)
                                                      pthread_cond_wait(&carEntered, &mutex);
                                                      port=false;
                                                      sensor = false;
                                                      --carWaitingIn;
                                                      ++numberOfcars;
                                                      while(numberOfcars >= maxCars)
                                                      {pthread_cond_wait(&freeSpace,&mutex);

                                                      }
                                    pthread_mutex_unlock(&mutex);
                  }
                  return (void *)0;
}

void *exit(void *arg)
{
                  while(true)
                  {
                                    pthread_mutex_lock(&mutex);

                                                      while(!carWaitingOut)
                                                      {pthread_cond_wait(&exitCond,&mutex);}

                                                      --carWaitingOut;
                                                      --numberOfcars;
                                                      pthread_cond_signal(&carCond);

                                                      if(numberOfcars<maxCars)
                                                      {
                                                                        pthread_cond_signal(&freeSpace);

                                                      }
                                    pthread_mutex_unlock(&mutex);
                  }
                  return (void *)0;
}

void *car(void *arg)
{
                  int carNumber = (int)arg;

                  while(true)
                  {
                  pthread_mutex_lock(&mutex);
                                    ++carWaitingIn;
                                    cout << "Car no. " << carNumber << " waiting at entry" << endl;
                                    pthread_cond_signal(&entryCond);

                                    while(!port)
                                    pthread_cond_wait(&carCond,&mutex);

                                    sensor = true;
                                    pthread_cond_signal(&carEntered);


                                    cout << "Car no. " << carNumber<< " at parking lot" << endl;
                  pthread_mutex_unlock(&mutex);

                  sleep(rand() % 5 + 3);

                  pthread_mutex_lock(&mutex);
                                    ++carWaitingOut;
                                    cout << "Car no. " << carNumber << " waiting at exit" << endl;
                                    pthread_cond_signal(&exitCond);

                                    while(carWaitingOut)
                                    {pthread_cond_wait(&carCond,&mutex);}

                  pthread_mutex_unlock(&mutex);
                  sleep(5);
                  }
                  return (void *)0;
}

int main(void)
{
                  void *exit_status;
                  int s;

                  cout<<"Creating threads"<<endl;
                  pthread_t carThread[10];
                  pthread_t entryThread;
                  pthread_t exitThread;
                  int value = 0;

                  s=pthread_create(&entryThread, NULL, entry, &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  for(int i=0;i<10;i++)
                  {
                                    s=pthread_create(&carThread[i], NULL, car, (void *)i);
                                    if(s != 0)
                                    {cout<<"Thread create error"<<endl;}
                  }



                  s=pthread_create(&exitThread, NULL, exit , &value);
                  if(s != 0)
                  {cout<<"Thread create error"<<endl;}

                  for(int i=0;i<10;i++)
                  {
                                    pthread_join(carThread[i], &exit_status);
                  }
                  pthread_join(entryThread, &exit_status);
                  pthread_join(exitThread, &exit_status);
                  cout<<"Threads terminated"<<endl;
                  return 0;
}


Console Output: 


1 comment:

  1. The goal of the exercise is to give you some routine in mapping real-world problems to multithreaded programmed solutions. You have completed the goal by making the program work. There are some minor details you could consider:
    You should have included a flowchart or pseudo code in your solution as described in the exercise, because it would make it easier to understand in what order everything happens. It would be a good idea to write when a car has left the parking lot, to check that it is able to pass through the exit guard. To make your code easier to understand you could use smaller spacing, but this is probably a limit in blogspot.

    ReplyDelete