Advertisement
Guest User

ferry.c

a guest
Nov 21st, 2021
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.37 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <pthread.h>
  5. #include <semaphore.h>
  6. #include <string.h>
  7. #include <stdbool.h>
  8. #include "ferry.h"
  9.  
  10. unsigned int numOfCars = 0;
  11. unsigned int numOfCarsWaiting = 0;
  12. unsigned int numOfCarsOnBoard = 0;
  13. pthread_mutex_t mutex;
  14. sem_t sem;
  15. bool isFerryPresent = false;
  16. bool isFerryTravelling = false;
  17.  
  18. void *embark(void *i)
  19. { // producer
  20.     int id = *((int *)i);
  21.     sleep(rand() % 5 + 1); // random arival time in range [1,5]
  22.     pthread_mutex_lock(&mutex);
  23.     numOfCarsWaiting++;
  24.     pthread_mutex_unlock(&mutex);
  25.     printf("Car #%d arrived at the port (cars waiting to board = %d)\n", id, numOfCarsWaiting);
  26.     // wait for the ferry to arrive
  27.     while (!isFerryPresent)
  28.         sleep(1);
  29.    
  30.     //tofix while the ferry hasn't left and is full, some cars reach this point
  31.     // we want them to wait until all cars have disembarked
  32.  
  33.     // start embarking if there is space on the ferry
  34.     sem_wait(&sem);
  35.     printf("Car #%d embarking on the ferry!\n", id);
  36.     pthread_mutex_lock(&mutex); // enter critical region
  37.     numOfCarsOnBoard++;
  38.     numOfCarsWaiting--;
  39.     pthread_mutex_unlock(&mutex); // leave critical region
  40.  
  41.     sleep(1); // embarking time
  42.     printf("Car #%d embarked on the ferry!\n", id);
  43.  
  44.     // while ferry is waiting or travelling sleep/stay embarked
  45.     while (isFerryPresent || isFerryTravelling)
  46.         sleep(1);
  47.  
  48.     // disembark from the ferry
  49.     pthread_mutex_lock(&mutex);
  50.     numOfCarsOnBoard--;
  51.     pthread_mutex_unlock(&mutex);
  52.     printf("Car #%d disemabarked from the ferry!\n", id);
  53.     sem_post(&sem);
  54.     free(i);
  55.     pthread_exit(NULL);
  56. }
  57.  
  58. void *initFerrySchedule()
  59. { // consumer
  60.     while (numOfCars > 0)
  61.     {
  62.         while (numOfCarsWaiting == 0 || numOfCarsOnBoard != 0)
  63.             sleep(1);
  64.         printf("Someone woke up the ferry!\nFerry is waiting for cars to board...\n");
  65.         // signal that boarding is allowed
  66.         pthread_mutex_lock(&mutex);
  67.         isFerryPresent = true;
  68.         isFerryTravelling = false;
  69.         pthread_mutex_unlock(&mutex);
  70.         sleep(7); // wait for cars to board
  71.         printf("Ferry is leaving with %d cars on board\n", numOfCarsOnBoard);
  72.         // signal that boarding is not allowed and cars
  73.         // should wait for the next ferry
  74.         pthread_mutex_lock(&mutex);
  75.         isFerryPresent = false;
  76.         isFerryTravelling = true;
  77.         numOfCars -= numOfCarsOnBoard;
  78.         pthread_mutex_unlock(&mutex);
  79.         // go to antirio
  80.         sleep(2); // travel time
  81.         printf("Ferry has reached Antirio!\n");
  82.         pthread_mutex_lock(&mutex);
  83.         isFerryTravelling = false;
  84.         pthread_mutex_unlock(&mutex);
  85.     }
  86.     pthread_exit(NULL);
  87. }
  88.  
  89. void parseCarArg(int argc, char *argv[])
  90. {
  91.     int i;
  92.     for (i = 0; i < argc; i++)
  93.     {
  94.         if (strcmp(argv[i], "-c") == 0)
  95.         {
  96.             if (++i < argc && strlen(argv[i]) > 0)
  97.                 numOfCars = strtol(argv[i], NULL, 10); // convert to long
  98.             if (numOfCars == 0)
  99.             {
  100.                 perror("You must enter a number of cars > 0!\n");
  101.                 exit(EXIT_FAILURE);
  102.             }
  103.             break;
  104.         }
  105.     }
  106. }
  107.  
  108. int main(int argc, char *argv[])
  109. {
  110.     if (argc == 0)
  111.         exit(EXIT_FAILURE);
  112.     parseCarArg(argc, argv);
  113.     srand(time(NULL)); // seed the generator using epoch time in millis
  114.  
  115.     if (sem_init(&sem, 0, MAX_FERRY_CAP) == -1) // up to 20 cars can board at a time
  116.     {
  117.         perror("Failed to initialize semaphore!\n");
  118.         exit(EXIT_FAILURE);
  119.     }
  120.  
  121.     if (pthread_mutex_init(&mutex, NULL) != 0)
  122.     {
  123.         perror("Failed to initialize mutex!\n");
  124.         exit(EXIT_FAILURE);
  125.     }
  126.  
  127.     pthread_t cars[numOfCars];
  128.     int i;
  129.     for (i = 0; i < numOfCars; i++)
  130.     {
  131.         int *id = malloc(sizeof(int));
  132.         *id = i;
  133.         if (pthread_create(&cars[i], NULL, embark, id) != 0)
  134.         {
  135.             perror("Failed to create threads for the cars!\n");
  136.             exit(EXIT_FAILURE);
  137.         }
  138.     }
  139.  
  140.     // ferry setup
  141.     pthread_t ferry;
  142.     pthread_create(&ferry, NULL, initFerrySchedule, NULL);
  143.     pthread_join(ferry, NULL);
  144.  
  145.     // wait for all threads to finish
  146.     for (i = 0; i < numOfCars; i++)
  147.         pthread_join(cars[i], NULL);
  148.     sem_destroy(&sem);
  149.     pthread_mutex_destroy(&mutex);
  150.     return 0;
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement