Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pthread.h>
- #include <semaphore.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "definitions.h"
- #include "resources.h"
- #include "vector.h"
- int washing_basins[NUM_WASHING_BASINS];
- vector free_toilets;
- State public_bathroom_state;
- /*
- * STUDENT TODO BEGIN:
- * Global locks, semaphores and condition variables
- */
- sem_t toiletSem;
- sem_t basinSem;
- pthread_mutex_t lockCabins;
- pthread_cond_t unlock;
- pthread_cond_t callStaff;
- pthread_mutex_t lockCont;
- pthread_mutex_t lockBasins;
- /*
- * STUDENT TODO END:
- */
- /*
- * STUDENT TODO:
- * signal all customers that the public bathroom has opened
- * Could a condition variable help?
- */
- void* doJanitor(void* param)
- {
- printf("Janitor is opening public bathroom for customers...\n");
- openPublicBathroom();
- printf("Janitor just opened public bathroom for customers...\n");
- pthread_mutex_lock(&lockCont);
- pthread_cond_broadcast(&unlock);
- public_bathroom_state = OPENED;
- pthread_mutex_unlock(&lockCont);
- coffeeBreak();
- printf("Janitor is calling in cleaning staff!\n");
- pthread_mutex_lock(&lockCont);
- pthread_cond_broadcast(&callStaff);
- public_bathroom_state = OPENED_AND_CLEANING_STAFF_NEEDED;
- pthread_mutex_unlock(&lockCont);
- return NULL;
- }
- /* STUDENT TODO:
- * make sure possible shared resources are locked correctly
- * How do you make sure that every customer can get to a washing basin?
- */
- void useWashingBasin(Customer* customer)
- {
- customWait(3);
- sem_wait(&basinSem);
- pthread_mutex_lock(&lockBasins);
- printf("Customer %zd goes to washing basins...\n", customer->customer_number);
- int i = 0;
- while (washing_basins[i] != 0)
- {
- i++;
- }
- washing_basins[i] = 1;
- printf("Customer %zd washes hands thoroughly...\n", customer->customer_number);
- pthread_mutex_unlock(&lockBasins);
- customWait(9);
- pthread_mutex_lock(&lockBasins);
- washing_basins[i] = 0;
- printf("Customer %zd left washing basins...\n", customer->customer_number);
- pthread_mutex_unlock(&lockBasins);
- sem_post(&basinSem);
- }
- /* STUDENT TODO:
- * make sure possible shared resources are locked correctly
- */
- Toilet* goIntoCabin(Customer* customer)
- {
- pthread_mutex_lock(&lockCont);
- pthread_cond_wait(&unlock, &lockCont);
- pthread_mutex_unlock(&lockCont);
- sem_wait(&toiletSem);
- pthread_mutex_lock(&lockCabins);
- Toilet* result = 0;
- printf("Customer %zd goes into cabin...\n", customer->customer_number);
- vector_iterator it = vector_begin(&free_toilets);
- for (; it != vector_end(&free_toilets); ++it)
- {
- Toilet* tmp = *it;
- if (!tmp->is_clogged)
- {
- result = *it;
- vector_erase(&free_toilets, it);
- break;
- }
- }
- if (!result)
- {
- printf("Urgh, customer %zd did not find a free and clean toilet!\n", customer->customer_number);
- }
- pthread_mutex_unlock(&lockCabins);
- return result;
- }
- void doBusiness()
- {
- customWait(9);
- }
- /* STUDENT TODO:
- * make sure possible shared resources are locked correctly
- */
- void leaveCabin(Customer* customer, Toilet* toilet)
- {
- pthread_mutex_lock(&lockCabins);
- toilet->is_clogged = isToiletClogged();
- vector_push_back(&free_toilets, toilet);
- printf("Customer %zd leaves toilet cabin...\n", customer->customer_number);
- if (!toilet->is_clogged)
- {
- printf("Customer %zd has manners :-)\n", customer->customer_number);
- sem_post(&toiletSem);
- }
- else
- {
- printf("Customer %zd is a pig :-(\n", customer->customer_number);
- }
- pthread_mutex_unlock(&lockCabins);
- }
- void* useToilet(void* customer)
- {
- Customer* current_customer = (Customer*)customer;
- Toilet* toilet = goIntoCabin(current_customer);
- doBusiness();
- leaveCabin(current_customer, toilet);
- useWashingBasin(current_customer);
- return NULL;
- }
- void cleanToilet(Toilet* toilet, ssize_t isLazy)
- {
- customWait(isLazy ? 14 : 7);
- toilet->is_clogged = 0;
- }
- /* STUDENT TODO:
- * make sure possible shared resources are locked correctly
- */
- void* doCleaning(void* cleaningStaff)
- {
- //Needed, because cleaning staff will still try to clean
- //toilets after all customer left and program ends
- //Same as in A1
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
- pthread_mutex_lock(&lockCont);
- pthread_cond_wait(&callStaff, &lockCont);
- pthread_mutex_unlock(&lockCont);
- CleaningStaff* current_staff = (CleaningStaff*)cleaningStaff;
- ssize_t id = (ssize_t)current_staff->employee_id;
- while (1)
- {
- pthread_mutex_lock(&lockCabins);
- printf("Cleaning staff %zd is looking for a toilet to be cleaned...\n", id);
- Toilet* toilet = 0;
- vector_iterator it = vector_begin(&free_toilets);
- for (; it != vector_end(&free_toilets); ++it)
- {
- Toilet* tmp = *it;
- if (tmp->is_clogged)
- {
- toilet = *it;
- vector_erase(&free_toilets, it);
- break;
- }
- }
- if (!toilet)
- {
- printf("Cleaning staff %zd has nothing to do... taking a short nap! *zZzZzZzZz*\n", id);
- pthread_mutex_unlock(&lockCabins);
- nanosleep((const struct timespec[]){{0, 1000L * 1000L * 50L}}, NULL);
- continue;
- }
- printf("Cleaning staff %zd is cleaning toilet %zd...\n", id, toilet->door_number);
- pthread_mutex_unlock(&lockCabins);
- cleanToilet(toilet, current_staff->is_lazy);
- pthread_mutex_lock(&lockCabins);
- printf("Cleaning staff %zd has cleaned toilet %zd\n", id, toilet->door_number);
- vector_push_back(&free_toilets, toilet);
- pthread_mutex_unlock(&lockCabins);
- sem_post(&toiletSem);
- }
- }
- int main(int argc, char* argv[])
- {
- /*
- * ONLY TOUCH THIS METHOD BETWEEN THE TODO COMMENTS!
- */
- srand(time(NULL));
- if (argc != 4)
- {
- fprintf(stderr, "Usage: %s <num_cleaning_staff> <num_customers> <num_toilets>\n", argv[0]);
- exit(-1);
- }
- ssize_t num_cleaning_staff = atoi(argv[1]);
- checkAllowedRange(num_cleaning_staff, NUM_CLEANING_STAFF);
- ssize_t num_customers = atoi(argv[2]);
- checkAllowedRange(num_customers, NUM_CUSTOMERS);
- ssize_t num_toilets = atoi(argv[3]);
- checkAllowedRange(num_toilets, NUM_TOILETS);
- CleaningStaff* staff = malloc(num_cleaning_staff * sizeof(CleaningStaff));
- Customer* customers = malloc(num_customers * sizeof(Customer));
- if (!staff || !customers)
- {
- free(staff);
- free(customers);
- fprintf(stderr, "Could not allocate memory!\n");
- exit(-1);
- }
- printf("Public toilet is opening!\n");
- /*
- * STUDENT TODO BEGIN:
- * Initialize the mutexes, semaphores and condition variables
- */
- pthread_cond_init(&unlock, NULL);
- pthread_cond_init(&callStaff, NULL);
- pthread_mutex_init(&lockBasins, NULL);
- pthread_mutex_init(&lockCabins, NULL);
- pthread_mutex_init(&lockCont, NULL);
- sem_init(&toiletSem, 0, num_toilets);
- sem_init(&basinSem, 0, NUM_WASHING_BASINS);
- /*
- * STUDENT TODO END
- */
- vector_init(&free_toilets);
- public_bathroom_state = CLOSED;
- for (ssize_t i = 0; i < num_toilets; i++)
- {
- Toilet* toilet = malloc(sizeof(Toilet));
- toilet->door_number = i;
- toilet->is_clogged = 0;
- vector_push_back(&free_toilets, toilet);
- }
- for (ssize_t i = 0; i < num_cleaning_staff; i++)
- {
- staff[i].employee_id = i;
- staff[i].is_lazy = rand() % 2;
- }
- for (ssize_t i = 0; i < num_customers; i++)
- {
- customers[i].customer_number = i;
- }
- for (ssize_t i = 0; i < num_cleaning_staff; i++)
- {
- pthread_create(&staff[i].employee, NULL, doCleaning, (void*)&staff[i]);
- }
- for (ssize_t i = 0; i < num_customers; i++)
- {
- pthread_create(&customers[i].customer, NULL, useToilet, (void*)&customers[i]);
- }
- pthread_t janitor_tid;
- pthread_create(&janitor_tid, NULL, doJanitor, NULL);
- for (ssize_t i = 0; i < num_customers; i++)
- {
- pthread_join(customers[i].customer, NULL);
- }
- printf("No more customers!\n");
- printf("Waiting for the Janitor to finish!\n");
- pthread_join(janitor_tid, NULL);
- for (ssize_t i = 0; i < num_cleaning_staff; i++)
- {
- pthread_cancel(staff[i].employee);
- pthread_join(staff[i].employee, NULL);
- }
- printf("Public toilet is closed!\n");
- /*
- * STUDENT TODO BEGIN:
- * Deinitialize the mutexes, semaphores and condition variables
- */
- pthread_mutex_destroy(&lockCabins);
- pthread_mutex_destroy(&lockBasins);
- pthread_mutex_destroy(&lockCont);
- pthread_cond_destroy(&unlock);
- pthread_cond_destroy(&callStaff);
- sem_destroy(&toiletSem);
- sem_destroy(&basinSem);
- /*
- * STUDENT TODO END
- */
- free(staff);
- free(customers);
- vector_iterator it = vector_begin(&free_toilets);
- while (it != vector_end(&free_toilets))
- {
- free(*it);
- vector_erase(&free_toilets, it);
- }
- vector_destroy(&free_toilets);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement