SHARE
TWEET

Untitled

a guest Oct 21st, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <pthread.h>
  2. #include <semaphore.h>
  3. #include <stdbool.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7.  
  8. #include "definitions.h"
  9. #include "resources.h"
  10. #include "vector.h"
  11.  
  12. int washing_basins[NUM_WASHING_BASINS];
  13. vector free_toilets;
  14. State public_bathroom_state;
  15.  
  16. /*
  17.  * STUDENT TODO BEGIN:
  18.  *  Global locks, semaphores and condition variables
  19.  */
  20. sem_t toiletSem;
  21. sem_t basinSem;
  22. pthread_mutex_t lockCabins;
  23. pthread_cond_t unlock;
  24. pthread_cond_t callStaff;
  25. pthread_mutex_t lockCont;
  26. pthread_mutex_t lockBasins;
  27. /*
  28.  * STUDENT TODO END:
  29.  */
  30.  
  31. /*
  32.  * STUDENT TODO:
  33.  *  signal all customers that the public bathroom has opened
  34.  *  Could a condition variable help?
  35.  */
  36. void* doJanitor(void* param)
  37. {
  38.   printf("Janitor is opening public bathroom for customers...\n");
  39.   openPublicBathroom();
  40.   printf("Janitor just opened public bathroom for customers...\n");
  41.   pthread_mutex_lock(&lockCont);
  42.   pthread_cond_broadcast(&unlock);
  43.   public_bathroom_state = OPENED;
  44.   pthread_mutex_unlock(&lockCont);
  45.   coffeeBreak();
  46.   printf("Janitor is calling in cleaning staff!\n");
  47.   pthread_mutex_lock(&lockCont);
  48.   pthread_cond_broadcast(&callStaff);
  49.   public_bathroom_state = OPENED_AND_CLEANING_STAFF_NEEDED;
  50.   pthread_mutex_unlock(&lockCont);
  51.  
  52.   return NULL;
  53. }
  54.  
  55. /* STUDENT TODO:
  56.  *  make sure possible shared resources are locked correctly
  57.  *  How do you make sure that every customer can get to a washing basin?
  58.  */
  59. void useWashingBasin(Customer* customer)
  60. {
  61.   customWait(3);
  62.  
  63.   sem_wait(&basinSem);
  64.   pthread_mutex_lock(&lockBasins);
  65.   printf("Customer %zd goes to washing basins...\n", customer->customer_number);
  66.   int i = 0;
  67.  
  68.   while (washing_basins[i] != 0)
  69.   {
  70.     i++;
  71.   }
  72.  
  73.   washing_basins[i] = 1;
  74.   printf("Customer %zd washes hands thoroughly...\n", customer->customer_number);
  75.   pthread_mutex_unlock(&lockBasins);
  76.  
  77.   customWait(9);
  78.  
  79.   pthread_mutex_lock(&lockBasins);
  80.   washing_basins[i] = 0;
  81.   printf("Customer %zd left washing basins...\n", customer->customer_number);
  82.   pthread_mutex_unlock(&lockBasins);
  83.   sem_post(&basinSem);
  84. }
  85.  
  86. /* STUDENT TODO:
  87.  *  make sure possible shared resources are locked correctly
  88.  */
  89. Toilet* goIntoCabin(Customer* customer)
  90. {
  91.   pthread_mutex_lock(&lockCont);
  92.   pthread_cond_wait(&unlock, &lockCont);
  93.   pthread_mutex_unlock(&lockCont);
  94.  
  95.   sem_wait(&toiletSem);
  96.   pthread_mutex_lock(&lockCabins);
  97.   Toilet* result = 0;
  98.   printf("Customer %zd goes into cabin...\n", customer->customer_number);
  99.   vector_iterator it = vector_begin(&free_toilets);
  100.  
  101.   for (; it != vector_end(&free_toilets); ++it)
  102.   {
  103.     Toilet* tmp = *it;
  104.     if (!tmp->is_clogged)
  105.     {
  106.       result = *it;
  107.       vector_erase(&free_toilets, it);
  108.      
  109.       break;
  110.     }
  111.   }
  112.   if (!result)
  113.   {
  114.     printf("Urgh, customer %zd did not find a free and clean toilet!\n", customer->customer_number);
  115.   }
  116.   pthread_mutex_unlock(&lockCabins);
  117.   return result;
  118. }
  119.  
  120. void doBusiness()
  121. {
  122.   customWait(9);
  123. }
  124.  
  125. /* STUDENT TODO:
  126.  *  make sure possible shared resources are locked correctly
  127.  */
  128. void leaveCabin(Customer* customer, Toilet* toilet)
  129. {
  130.   pthread_mutex_lock(&lockCabins);
  131.   toilet->is_clogged = isToiletClogged();
  132.   vector_push_back(&free_toilets, toilet);
  133.   printf("Customer %zd leaves toilet cabin...\n", customer->customer_number);
  134.  
  135.   if (!toilet->is_clogged)
  136.   {
  137.     printf("Customer %zd has manners :-)\n", customer->customer_number);
  138.     sem_post(&toiletSem);
  139.   }
  140.   else
  141.   {
  142.     printf("Customer %zd is a pig :-(\n", customer->customer_number);
  143.   }
  144.   pthread_mutex_unlock(&lockCabins);
  145. }
  146.  
  147. void* useToilet(void* customer)
  148. {
  149.   Customer* current_customer = (Customer*)customer;
  150.   Toilet* toilet = goIntoCabin(current_customer);
  151.   doBusiness();
  152.   leaveCabin(current_customer, toilet);
  153.   useWashingBasin(current_customer);
  154.  
  155.   return NULL;
  156. }
  157.  
  158. void cleanToilet(Toilet* toilet, ssize_t isLazy)
  159. {
  160.   customWait(isLazy ? 14 : 7);
  161.   toilet->is_clogged = 0;
  162. }
  163.  
  164. /* STUDENT TODO:
  165.  *  make sure possible shared resources are locked correctly
  166.  */
  167. void* doCleaning(void* cleaningStaff)
  168. {
  169.   //Needed, because cleaning staff will still try to clean
  170.   //toilets after all customer left and program ends
  171.   //Same as in A1
  172.   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  173.  
  174.   pthread_mutex_lock(&lockCont);
  175.   pthread_cond_wait(&callStaff, &lockCont);
  176.   pthread_mutex_unlock(&lockCont);
  177.   CleaningStaff* current_staff = (CleaningStaff*)cleaningStaff;
  178.   ssize_t id = (ssize_t)current_staff->employee_id;
  179.  
  180.   while (1)
  181.   {
  182.     pthread_mutex_lock(&lockCabins);
  183.     printf("Cleaning staff %zd is looking for a toilet to be cleaned...\n", id);
  184.    
  185.     Toilet* toilet = 0;
  186.  
  187.     vector_iterator it = vector_begin(&free_toilets);
  188.     for (; it != vector_end(&free_toilets); ++it)
  189.     {
  190.       Toilet* tmp = *it;
  191.       if (tmp->is_clogged)
  192.       {
  193.         toilet = *it;
  194.         vector_erase(&free_toilets, it);
  195.        
  196.         break;
  197.       }
  198.     }
  199.    
  200.     if (!toilet)
  201.     {
  202.       printf("Cleaning staff %zd has nothing to do... taking a short nap! *zZzZzZzZz*\n", id);
  203.       pthread_mutex_unlock(&lockCabins);
  204.       nanosleep((const struct timespec[]){{0, 1000L * 1000L * 50L}}, NULL);
  205.       continue;
  206.     }
  207.  
  208.     printf("Cleaning staff %zd is cleaning toilet %zd...\n", id, toilet->door_number);
  209.  
  210.     pthread_mutex_unlock(&lockCabins);
  211.     cleanToilet(toilet, current_staff->is_lazy);
  212.     pthread_mutex_lock(&lockCabins);
  213.    
  214.     printf("Cleaning staff %zd has cleaned toilet %zd\n", id, toilet->door_number);
  215.     vector_push_back(&free_toilets, toilet);
  216.    
  217.     pthread_mutex_unlock(&lockCabins);
  218.     sem_post(&toiletSem);
  219.   }
  220. }
  221.  
  222. int main(int argc, char* argv[])
  223. {
  224.   /*
  225.    * ONLY TOUCH THIS METHOD BETWEEN THE TODO COMMENTS!
  226.    */
  227.   srand(time(NULL));
  228.   if (argc != 4)
  229.   {
  230.     fprintf(stderr, "Usage: %s <num_cleaning_staff> <num_customers> <num_toilets>\n", argv[0]);
  231.     exit(-1);
  232.   }
  233.  
  234.   ssize_t num_cleaning_staff = atoi(argv[1]);
  235.   checkAllowedRange(num_cleaning_staff, NUM_CLEANING_STAFF);
  236.  
  237.   ssize_t num_customers = atoi(argv[2]);
  238.   checkAllowedRange(num_customers, NUM_CUSTOMERS);
  239.  
  240.   ssize_t num_toilets = atoi(argv[3]);
  241.   checkAllowedRange(num_toilets, NUM_TOILETS);
  242.  
  243.   CleaningStaff* staff = malloc(num_cleaning_staff * sizeof(CleaningStaff));
  244.   Customer* customers = malloc(num_customers * sizeof(Customer));
  245.  
  246.   if (!staff || !customers)
  247.   {
  248.     free(staff);
  249.     free(customers);
  250.     fprintf(stderr, "Could not allocate memory!\n");
  251.     exit(-1);
  252.   }
  253.  
  254.   printf("Public toilet is opening!\n");
  255.  
  256.   /*
  257.    * STUDENT TODO BEGIN:
  258.    *  Initialize the mutexes, semaphores and condition variables
  259.    */
  260.   pthread_cond_init(&unlock, NULL);
  261.   pthread_cond_init(&callStaff, NULL);
  262.  
  263.   pthread_mutex_init(&lockBasins, NULL);
  264.   pthread_mutex_init(&lockCabins, NULL);
  265.   pthread_mutex_init(&lockCont, NULL);
  266.  
  267.   sem_init(&toiletSem, 0, num_toilets);
  268.   sem_init(&basinSem, 0, NUM_WASHING_BASINS);
  269.  
  270.   /*
  271.    * STUDENT TODO END
  272.    */
  273.  
  274.   vector_init(&free_toilets);
  275.   public_bathroom_state = CLOSED;
  276.  
  277.   for (ssize_t i = 0; i < num_toilets; i++)
  278.   {
  279.     Toilet* toilet = malloc(sizeof(Toilet));
  280.     toilet->door_number = i;
  281.     toilet->is_clogged = 0;
  282.     vector_push_back(&free_toilets, toilet);
  283.   }
  284.  
  285.   for (ssize_t i = 0; i < num_cleaning_staff; i++)
  286.   {
  287.     staff[i].employee_id = i;
  288.     staff[i].is_lazy = rand() % 2;
  289.   }
  290.  
  291.   for (ssize_t i = 0; i < num_customers; i++)
  292.   {
  293.     customers[i].customer_number = i;
  294.   }
  295.  
  296.   for (ssize_t i = 0; i < num_cleaning_staff; i++)
  297.   {
  298.     pthread_create(&staff[i].employee, NULL, doCleaning, (void*)&staff[i]);
  299.   }
  300.  
  301.   for (ssize_t i = 0; i < num_customers; i++)
  302.   {
  303.     pthread_create(&customers[i].customer, NULL, useToilet, (void*)&customers[i]);
  304.   }
  305.  
  306.   pthread_t janitor_tid;
  307.   pthread_create(&janitor_tid, NULL, doJanitor, NULL);
  308.  
  309.   for (ssize_t i = 0; i < num_customers; i++)
  310.   {
  311.     pthread_join(customers[i].customer, NULL);
  312.   }
  313.   printf("No more customers!\n");
  314.  
  315.   printf("Waiting for the Janitor to finish!\n");
  316.   pthread_join(janitor_tid, NULL);
  317.  
  318.   for (ssize_t i = 0; i < num_cleaning_staff; i++)
  319.   {
  320.     pthread_cancel(staff[i].employee);
  321.     pthread_join(staff[i].employee, NULL);
  322.   }
  323.  
  324.   printf("Public toilet is closed!\n");
  325.  
  326.   /*
  327.    * STUDENT TODO BEGIN:
  328.    *  Deinitialize the mutexes, semaphores and condition variables
  329.    */
  330.   pthread_mutex_destroy(&lockCabins);
  331.  
  332.   pthread_mutex_destroy(&lockBasins);
  333.   pthread_mutex_destroy(&lockCont);
  334.  
  335.   pthread_cond_destroy(&unlock);
  336.   pthread_cond_destroy(&callStaff);
  337.  
  338.   sem_destroy(&toiletSem);
  339.   sem_destroy(&basinSem);
  340.  
  341.   /*
  342.    * STUDENT TODO END
  343.    */
  344.  
  345.   free(staff);
  346.   free(customers);
  347.  
  348.   vector_iterator it = vector_begin(&free_toilets);
  349.   while (it != vector_end(&free_toilets))
  350.   {
  351.     free(*it);
  352.     vector_erase(&free_toilets, it);
  353.   }
  354.   vector_destroy(&free_toilets);
  355.  
  356.   return 0;
  357. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top