Advertisement
Guest User

Untitled

a guest
May 2nd, 2024
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.46 KB | None | 0 0
  1. /*
  2. assignment:
  3.  
  4. The program starts threads for a vending machine, a supplier, and customers:
  5. • The vending machine waits for a coin to be inserted, then dispenses an item, or returns the coin if the stock is depleted.
  6. • The supplier opens the vending machine, restocks items, and closes it again.
  7. • Customers arrive at the vending machine one by one, insert a coin, and either collect an item or the returned coin and leave.
  8. Only one person can interact with the vending machine at a time.
  9.  
  10. Implement the specific behavior of threads according to the provided description.
  11.  
  12. Ensure critical sections are as short as possible and synchronize actions to follow each other correctly without unnecessary delays:
  13. • Synchronously start all people,
  14. • Order actions during interaction with the vending machine.
  15.  
  16. Each activity is represented by corresponding outputs.
  17. Introducing any delay at any point must not affect the correctness of the program's behavior.
  18.  
  19. The use of active waiting is not permitted.
  20.  
  21. Use POSIX barriers and unnamed semaphores for synchronization.
  22. Use POSIX thread mutexes to handle critical sections.
  23. Optimize the number of used variables (use only the minimum necessary).
  24.  
  25. Name variables appropriately according to their purpose.
  26. For synchronization semaphores, it is recommended that the semaphore variable name reflects the activity for which this semaphore is waited on
  27.  
  28. */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <pthread.h>
  35. #include <stdbool.h>
  36. #include <stdbool.h>
  37. #include <inttypes.h> // intptr_t
  38. #include <semaphore.h>
  39.  
  40. // ANSI color escape sequences
  41. #define C_NORMAL "\x1B[0m"
  42. #define C_RED "\x1B[1;31m"
  43. #define C_DARK_RED "\x1B[0;31m"
  44. #define C_GREEN "\x1B[1;32m"
  45. #define C_BLUE "\x1B[1;34m"
  46. #define C_CYAN "\x1B[1;36m"
  47. #define C_MAGENTA "\x1B[1;35m"
  48. #define C_PURPLE "\x1B[0;35m"
  49. #define C_YELLOW "\x1B[1;33m"
  50. #define C_BROWN "\x1B[0;33m"
  51.  
  52. // colors
  53. #define CLR_NORMAL C_NORMAL
  54. // vending machine
  55. #define CLR_VM C_PURPLE
  56. #define CLR_VM_TEXT C_NORMAL
  57. #define CLR_VM_ITEM C_GREEN
  58. #define CLR_VM_ERR C_RED
  59. // customer
  60. #define CLR_C C_BROWN
  61. #define CLR_C_TEXT C_NORMAL
  62. #define CLR_C_ITEM C_CYAN
  63. #define CLR_C_ERR C_RED
  64. // supplier
  65. #define CLR_S C_BLUE
  66. #define CLR_S_TEXT C_NORMAL
  67.  
  68. // vending machine printf macros
  69. #define vm_printf(out, color, text, item...) \
  70. fprintf(out, CLR_VM "%15s:" color " " text CLR_NORMAL "\n", "vending-machine", ##item)
  71. #define vmn_printf(t, item...) vm_printf(stdout, CLR_VM_TEXT, t, ##item)
  72. #define vme_printf(t, item...) vm_printf(stderr, CLR_VM_ERR, t, ##item)
  73.  
  74. // customer printf macros
  75. #define c_fprintf(out, color, text, id, item...) \
  76. fprintf(out, CLR_C "%12s%3" PRIdPTR ":" color " " text CLR_NORMAL "\n", "customer", id, ##item)
  77. #define cn_printf(t, id, item...) c_fprintf(stdout, CLR_C_TEXT, t, id, ##item)
  78. #define ce_printf(t, id, item...) c_fprintf(stderr, CLR_C_ERR, t, id, ##item)
  79.  
  80. // supplier printf macros
  81. #define s_printf(out, color, text, item...) \
  82. fprintf(out, CLR_S "%15s:" color " " text CLR_NORMAL "\n", "supplier", ##item)
  83. #define sn_printf(t, item...) s_printf(stdout, CLR_S_TEXT, t, ##item)
  84.  
  85. // max & default values
  86. #define MAX_PEOPLE 99
  87. #define DEFAULT_PEOPLE 4
  88. #define MAX_ITEMS 99
  89. #define DEFAULT_ITEMS 1
  90. #define DEFAULT_SUPPLY 3
  91.  
  92. int customers = DEFAULT_PEOPLE; // the number of customers
  93. volatile int items = DEFAULT_ITEMS; // the number of items
  94. volatile int supply = DEFAULT_SUPPLY; // the number of newly delivered items
  95. volatile int item_id = -1; // item id (0 = refund)
  96.  
  97. //my modification
  98. pthread_barrier_t sync_start_threads;
  99. pthread_mutex_t mutex_receiving_id = PTHREAD_MUTEX_INITIALIZER;
  100. pthread_mutex_t mutex_releasing_id = PTHREAD_MUTEX_INITIALIZER;
  101. pthread_mutex_t mutex_supply = PTHREAD_MUTEX_INITIALIZER;
  102. // end of my modification
  103.  
  104. // synchronization and critical section variables
  105.  
  106. // release all allocated resources, used in atexit(3)
  107. void release_resources(void)
  108. {
  109. }
  110.  
  111. // synchronize people: all are starting at once
  112. void sync_threads_start()
  113. {
  114. //my code
  115. pthread_barrier_wait(&sync_start_threads);
  116. //end of my code
  117. }
  118.  
  119. // vending machine thread
  120. void *vending_machine(void *arg)
  121. {
  122. while (true) {
  123. vmn_printf("Waiting for a coin.");
  124. vmn_printf("Coin accepted.");
  125. usleep(1000); // working
  126. //my code
  127. pthread_mutex_lock(&mutex_releasing_id);
  128. //my code
  129. if (items) {
  130. item_id = items--;
  131. vmn_printf("Releasing item id " CLR_C_ITEM "#%d" CLR_NORMAL ".", item_id);
  132. }
  133. else {
  134. vme_printf("No more items, refunding.");
  135. item_id = 0;
  136. }
  137. //my code
  138. pthread_mutex_unlock(&mutex_releasing_id);
  139. //my code
  140. vmn_printf("Logging the transaction.");
  141. }
  142. return NULL;
  143. }
  144.  
  145. // customers thread
  146. void *customer(intptr_t *id)
  147. {
  148. sync_threads_start();
  149. cn_printf("Coming to the vending machine.", *id);
  150. cn_printf("Starting interaction: Inserting a coin.", *id);
  151. cn_printf("Waiting for an item.", *id);
  152. //my code
  153. pthread_mutex_lock(&mutex_receiving_id);
  154. //end of my code
  155. if (item_id)
  156. cn_printf("Received item id " CLR_VM_ITEM "#%d" CLR_NORMAL ".", *id, item_id);
  157. else
  158. ce_printf("Received the coin back.", *id);
  159. cn_printf("On my way away.", *id);
  160. //my code
  161. pthread_mutex_unlock(&mutex_receiving_id);
  162. //end of my code
  163. return NULL;
  164. }
  165.  
  166. // supplier thread
  167. void *supplier(void *arg)
  168. {
  169. sync_threads_start();
  170. sn_printf("Coming to the vending machine.");
  171. sn_printf("Opening the vending machine to restock it.");
  172. //my code
  173. pthread_mutex_lock(&mutex_supply);
  174. //end of my code
  175. items += supply;
  176. //my code
  177. pthread_mutex_unlock(&mutex_supply)
  178. //end of my code
  179. sn_printf("Closing the vending machine after restocking it.");
  180. sn_printf("On my way to another vending machine.");
  181. return NULL;
  182. }
  183.  
  184.  
  185. int main(int argc, char *argv[])
  186. {
  187. pthread_t tid_vm;
  188. pthread_t tid_s;
  189. pthread_t tid_customers[MAX_PEOPLE];
  190. intptr_t id_customers[MAX_PEOPLE];
  191. int t;
  192.  
  193. // the number of customers from argv[1]
  194. if (argc > 1)
  195. customers = strtol(argv[1], NULL, 0);
  196. if (customers > MAX_PEOPLE)
  197. customers = MAX_PEOPLE;
  198.  
  199. // the number of items from argv[2]
  200. if (argc > 2)
  201. items = strtol(argv[2], NULL, 0);
  202. if (items > MAX_ITEMS)
  203. items = MAX_ITEMS;
  204.  
  205. // the number of supplies from argv[3]
  206. if (argc > 3)
  207. supply = strtol(argv[3], NULL, 0);
  208. if (supply > MAX_ITEMS)
  209. supply = MAX_ITEMS;
  210.  
  211. atexit(release_resources); // release resources at program exit
  212.  
  213. // print id
  214.  
  215. // initialize
  216. //my code
  217. pthread_barrier_init(&sync_start_threads, NULL, MAX_PEOPLE);
  218. //end of my code
  219. // create threads
  220. if ((errno = pthread_create(&tid_vm, NULL, vending_machine, NULL))) {
  221. perror("pthread_create failed");
  222. return EXIT_FAILURE;
  223. }
  224. for (t = 0; t < customers; ++t) {
  225. id_customers[t] = t;
  226. if ((errno = pthread_create(&tid_customers[t], NULL, (void *(*)(void *))customer, &id_customers[t]))) {
  227. perror("pthread_create failed");
  228. return EXIT_FAILURE;
  229. }
  230. }
  231. if ((errno = pthread_create(&tid_s, NULL, supplier, NULL))) {
  232. perror("pthread_create failed");
  233. return EXIT_FAILURE;
  234. }
  235.  
  236. // join all threads
  237. // all thread ids are correctly used, threads do exist, thus no error checking
  238. pthread_join(tid_s, NULL); // supplier
  239. for (t = 0; t < customers; ++t)
  240. pthread_join(tid_customers[t], NULL); // customers
  241. pthread_cancel(tid_vm); // terminate the vending machine thread
  242. pthread_join(tid_vm, NULL); // vending machine
  243. }
  244.  
  245. // vim:ts=4:sw=4
  246. // EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement