#include #include #include #include #include /**** * * This is a skeleton for assignment 3. It includes the code to handle the * production and clean up of customers. Your job, is to write the barista * threads and manage the buffers (pthread_mutexes will be your friend). * * */ /** * Definition of the maximum buffer size */ #define MAX_BUFFER_SIZE 10 /** * Definition of how many customers we will processes and how many * baristas we'll have serve them */ #define TOTAL_CUSTOMERS 15 #define TOTAL_BARISTAS 2 /* Data structure to pass data to the customer thread */ typedef struct _customer_data_t { int tid; } customer_data_t; /* Data structure to pass data to the cleaner thread */ typedef struct _cleaner_data_t { int tid; } cleaner_data_t; /* Data structures to organize information about the order */ typedef struct _item_t { int production_time_ms; } item_t; typedef struct _order_t { int customer; int size; item_t items []; } order_t; /** * Buffer to manage the order data */ order_t ** order_buffer; int order_index; /** * Buffer to manage the returned "products" */ int * bar_buffer; int bar_index; /** * Integer to play the "cash register" */ int cash; /* Counter for how many customers yet to processes */ int customer_total = TOTAL_CUSTOMERS; /* * Calculate the amount for the customer thread to sleep */ int decide_time_to_sleep(struct timespec *st) { int adjust_ms, base_ms; /* Assume we want to wait about half a second */ base_ms = 500; adjust_ms = (rand() % 500) - 250; /* Set adjusted time in timespec */ st->tv_sec = 0; st->tv_nsec = (base_ms + adjust_ms) * 1000000L; } /* * Generate how long a barista must "work" to make the order */ int generate_prduction_time_ms() { int c = (rand() % 3); switch(c) { case 0 : return(200); break; case 1 : return(400); break; case 2 : return(800); break; } } /* * For a given order size, generate items to be produced */ int generate_order (order_t * order) { int i; for (i = 0; i < order->size; i++) { item_t order_part; order_part.production_time_ms = generate_prduction_time_ms(); order->items[i] = order_part; } } /* * Generate a size for an order */ int generate_order_size() { int o_size; o_size = (rand() % 4) + 1; return(o_size); } void print_order(order_t * order) { printf("Order %d (%d)\n", order->customer, order->size); for(int i = 0; i < order->size; i++) { printf("\tItem %d: %d\n", i, order->items[i].production_time_ms); } } /* * Main Customer Thread function. * * Generate customers and orders over time, clean up as customers are * served. */ void *customer_run(void *arg) { customer_data_t *data = (customer_data_t *)arg; int customer_id = 0; int order_size = 0; /* Run for as long as we have customers incoming */ while (customer_total > 0) { /* Create customer and generate order */ printf("Created Customer %d\n", customer_id++); order_size = generate_order_size(); order_t * new_order = malloc(sizeof (order_t) + sizeof (item_t [order_size])); new_order->customer=customer_id; new_order->size=order_size; printf("Ordering %d items\n", new_order->size); generate_order(new_order); order_buffer[order_index] = new_order; order_index++; /* Put the thread to sleep until the next customer comes */ struct timespec c; decide_time_to_sleep(&c); printf("Sleeping Until Next Customer in: %lld.%.3ld\n", (long long)c.tv_sec, c.tv_nsec); struct timespec r; nanosleep(&c, &r); customer_total--; } pthread_exit(NULL); } void *cleanup_run(void *arg) { int customers_cleared = 0; int cash_total; int bar; while (customers_cleared < TOTAL_CUSTOMERS) { /* Take the next bar out of the buffer */ bar_index--; bar = bar_buffer[bar_index]; customers_cleared++; cash_total = cash; printf("Cleared %d customers - Cash (%d)\n", customers_cleared, cash_total); } pthread_exit(NULL); } /* * Run the main simulation */ int main(int argc, char **argv) { int i, rc; /* Intializes random number generator */ time_t t; srand((unsigned) time(&t)); /* Initalize buffers */ order_buffer = malloc (sizeof(order_t) * MAX_BUFFER_SIZE); order_index = 0; bar_buffer = malloc (sizeof(int) * MAX_BUFFER_SIZE); bar_index = 0; cash=0; /* Create Customer Thread */ pthread_t cust_t; customer_data_t cust_data; cust_data.tid=1000; if ((rc = pthread_create(&cust_t, NULL, customer_run, &cust_data))) { fprintf(stderr, "error: pthread_create, rc: %d\n", rc); return EXIT_FAILURE; } /* Create Cleaner Thread */ pthread_t cleaner_t; cleaner_data_t cleaner_data; cleaner_data.tid=1001; if ((rc = pthread_create(&cleaner_t, NULL, cleanup_run, &cleaner_data))) { fprintf(stderr, "error: pthread_create, rc: %d\n", rc); return EXIT_FAILURE; } /* Create Barista Threads */ /* block until all threads complete */ for (i = 0; i < barista_count; ++i) { } pthread_join(cust_t, NULL); pthread_join(cleaner_t, NULL); return EXIT_SUCCESS; }