Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.83 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement