Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- assignment:
- The program starts threads for a vending machine, a supplier, and customers:
- • The vending machine waits for a coin to be inserted, then dispenses an item, or returns the coin if the stock is depleted.
- • The supplier opens the vending machine, restocks items, and closes it again.
- • Customers arrive at the vending machine one by one, insert a coin, and either collect an item or the returned coin and leave.
- Only one person can interact with the vending machine at a time.
- Implement the specific behavior of threads according to the provided description.
- Ensure critical sections are as short as possible and synchronize actions to follow each other correctly without unnecessary delays:
- • Synchronously start all people,
- • Order actions during interaction with the vending machine.
- Each activity is represented by corresponding outputs.
- Introducing any delay at any point must not affect the correctness of the program's behavior.
- The use of active waiting is not permitted.
- Use POSIX barriers and unnamed semaphores for synchronization.
- Use POSIX thread mutexes to handle critical sections.
- Optimize the number of used variables (use only the minimum necessary).
- Name variables appropriately according to their purpose.
- For synchronization semaphores, it is recommended that the semaphore variable name reflects the activity for which this semaphore is waited on
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <pthread.h>
- #include <stdbool.h>
- #include <stdbool.h>
- #include <inttypes.h> // intptr_t
- #include <semaphore.h>
- // ANSI color escape sequences
- #define C_NORMAL "\x1B[0m"
- #define C_RED "\x1B[1;31m"
- #define C_DARK_RED "\x1B[0;31m"
- #define C_GREEN "\x1B[1;32m"
- #define C_BLUE "\x1B[1;34m"
- #define C_CYAN "\x1B[1;36m"
- #define C_MAGENTA "\x1B[1;35m"
- #define C_PURPLE "\x1B[0;35m"
- #define C_YELLOW "\x1B[1;33m"
- #define C_BROWN "\x1B[0;33m"
- // colors
- #define CLR_NORMAL C_NORMAL
- // vending machine
- #define CLR_VM C_PURPLE
- #define CLR_VM_TEXT C_NORMAL
- #define CLR_VM_ITEM C_GREEN
- #define CLR_VM_ERR C_RED
- // customer
- #define CLR_C C_BROWN
- #define CLR_C_TEXT C_NORMAL
- #define CLR_C_ITEM C_CYAN
- #define CLR_C_ERR C_RED
- // supplier
- #define CLR_S C_BLUE
- #define CLR_S_TEXT C_NORMAL
- // vending machine printf macros
- #define vm_printf(out, color, text, item...) \
- fprintf(out, CLR_VM "%15s:" color " " text CLR_NORMAL "\n", "vending-machine", ##item)
- #define vmn_printf(t, item...) vm_printf(stdout, CLR_VM_TEXT, t, ##item)
- #define vme_printf(t, item...) vm_printf(stderr, CLR_VM_ERR, t, ##item)
- // customer printf macros
- #define c_fprintf(out, color, text, id, item...) \
- fprintf(out, CLR_C "%12s%3" PRIdPTR ":" color " " text CLR_NORMAL "\n", "customer", id, ##item)
- #define cn_printf(t, id, item...) c_fprintf(stdout, CLR_C_TEXT, t, id, ##item)
- #define ce_printf(t, id, item...) c_fprintf(stderr, CLR_C_ERR, t, id, ##item)
- // supplier printf macros
- #define s_printf(out, color, text, item...) \
- fprintf(out, CLR_S "%15s:" color " " text CLR_NORMAL "\n", "supplier", ##item)
- #define sn_printf(t, item...) s_printf(stdout, CLR_S_TEXT, t, ##item)
- // max & default values
- #define MAX_PEOPLE 99
- #define DEFAULT_PEOPLE 4
- #define MAX_ITEMS 99
- #define DEFAULT_ITEMS 1
- #define DEFAULT_SUPPLY 3
- int customers = DEFAULT_PEOPLE; // the number of customers
- volatile int items = DEFAULT_ITEMS; // the number of items
- volatile int supply = DEFAULT_SUPPLY; // the number of newly delivered items
- volatile int item_id = -1; // item id (0 = refund)
- //my modification
- pthread_barrier_t sync_start_threads;
- pthread_mutex_t mutex_receiving_id = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_t mutex_releasing_id = PTHREAD_MUTEX_INITIALIZER;
- pthread_mutex_t mutex_supply = PTHREAD_MUTEX_INITIALIZER;
- // end of my modification
- // synchronization and critical section variables
- // release all allocated resources, used in atexit(3)
- void release_resources(void)
- {
- }
- // synchronize people: all are starting at once
- void sync_threads_start()
- {
- //my code
- pthread_barrier_wait(&sync_start_threads);
- //end of my code
- }
- // vending machine thread
- void *vending_machine(void *arg)
- {
- while (true) {
- vmn_printf("Waiting for a coin.");
- vmn_printf("Coin accepted.");
- usleep(1000); // working
- //my code
- pthread_mutex_lock(&mutex_releasing_id);
- //my code
- if (items) {
- item_id = items--;
- vmn_printf("Releasing item id " CLR_C_ITEM "#%d" CLR_NORMAL ".", item_id);
- }
- else {
- vme_printf("No more items, refunding.");
- item_id = 0;
- }
- //my code
- pthread_mutex_unlock(&mutex_releasing_id);
- //my code
- vmn_printf("Logging the transaction.");
- }
- return NULL;
- }
- // customers thread
- void *customer(intptr_t *id)
- {
- sync_threads_start();
- cn_printf("Coming to the vending machine.", *id);
- cn_printf("Starting interaction: Inserting a coin.", *id);
- cn_printf("Waiting for an item.", *id);
- //my code
- pthread_mutex_lock(&mutex_receiving_id);
- //end of my code
- if (item_id)
- cn_printf("Received item id " CLR_VM_ITEM "#%d" CLR_NORMAL ".", *id, item_id);
- else
- ce_printf("Received the coin back.", *id);
- cn_printf("On my way away.", *id);
- //my code
- pthread_mutex_unlock(&mutex_receiving_id);
- //end of my code
- return NULL;
- }
- // supplier thread
- void *supplier(void *arg)
- {
- sync_threads_start();
- sn_printf("Coming to the vending machine.");
- sn_printf("Opening the vending machine to restock it.");
- //my code
- pthread_mutex_lock(&mutex_supply);
- //end of my code
- items += supply;
- //my code
- pthread_mutex_unlock(&mutex_supply)
- //end of my code
- sn_printf("Closing the vending machine after restocking it.");
- sn_printf("On my way to another vending machine.");
- return NULL;
- }
- int main(int argc, char *argv[])
- {
- pthread_t tid_vm;
- pthread_t tid_s;
- pthread_t tid_customers[MAX_PEOPLE];
- intptr_t id_customers[MAX_PEOPLE];
- int t;
- // the number of customers from argv[1]
- if (argc > 1)
- customers = strtol(argv[1], NULL, 0);
- if (customers > MAX_PEOPLE)
- customers = MAX_PEOPLE;
- // the number of items from argv[2]
- if (argc > 2)
- items = strtol(argv[2], NULL, 0);
- if (items > MAX_ITEMS)
- items = MAX_ITEMS;
- // the number of supplies from argv[3]
- if (argc > 3)
- supply = strtol(argv[3], NULL, 0);
- if (supply > MAX_ITEMS)
- supply = MAX_ITEMS;
- atexit(release_resources); // release resources at program exit
- // print id
- // initialize
- //my code
- pthread_barrier_init(&sync_start_threads, NULL, MAX_PEOPLE);
- //end of my code
- // create threads
- if ((errno = pthread_create(&tid_vm, NULL, vending_machine, NULL))) {
- perror("pthread_create failed");
- return EXIT_FAILURE;
- }
- for (t = 0; t < customers; ++t) {
- id_customers[t] = t;
- if ((errno = pthread_create(&tid_customers[t], NULL, (void *(*)(void *))customer, &id_customers[t]))) {
- perror("pthread_create failed");
- return EXIT_FAILURE;
- }
- }
- if ((errno = pthread_create(&tid_s, NULL, supplier, NULL))) {
- perror("pthread_create failed");
- return EXIT_FAILURE;
- }
- // join all threads
- // all thread ids are correctly used, threads do exist, thus no error checking
- pthread_join(tid_s, NULL); // supplier
- for (t = 0; t < customers; ++t)
- pthread_join(tid_customers[t], NULL); // customers
- pthread_cancel(tid_vm); // terminate the vending machine thread
- pthread_join(tid_vm, NULL); // vending machine
- }
- // vim:ts=4:sw=4
- // EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement