From 24c0d9e89b80b8b2257eefd154cfcd06f0c46048 Mon Sep 17 00:00:00 2001 From: Brychan Dempsey Date: Fri, 30 Apr 2021 15:15:14 +1200 Subject: [PATCH] Cleaned code --- .gitignore | 1 + assignment2 | Bin 22336 -> 22296 bytes assignment2_handout.c | 441 ++++++++++++++++++++++++++---------------- 3 files changed, 280 insertions(+), 162 deletions(-) diff --git a/.gitignore b/.gitignore index eed0dc1..3ef2bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ assignment2.exe +assignment2 diff --git a/assignment2 b/assignment2 index d9efe6d7877268b515ea7a3ed88ac54e404ed069..ac31dd5dda4ebdce5586b3e43ff8e33161487638 100644 GIT binary patch delta 5348 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 diff --git a/assignment2_handout.c b/assignment2_handout.c index 22ab8c1..586b66d 100644 --- a/assignment2_handout.c +++ b/assignment2_handout.c @@ -11,39 +11,39 @@ // -------------------------------------------------- // Define Problem Size // -------------------------------------------------- -#define NLIFTS 4 // The number of lifts in the building -#define NFLOORS 20 // The number of floors in the building -#define NPEOPLE 3 // The number of people in the building -#define MAXNOINLIFT 10 // Maximum number of people in a lift - +#define NLIFTS 4 // The number of lifts in the building +#define NFLOORS 20 // The number of floors in the building +#define NPEOPLE 20 // The number of people in the building +#define MAXNOINLIFT 10 // Maximum number of people in a lift // -------------------------------------------------- // Define delay times (in milliseconds) // -------------------------------------------------- //#define SUPERSLOW //#define SLOW - //#define FAST - #define SUPERFAST +//#define FAST +#define SUPERFAST + #if defined(SUPERSLOW) - #define LIFTSPEED 500 // The time it takes for the lift to move one floor - #define GETINSPEED 250 // The time it takes to get into the lift - #define GETOUTSPEED 250 // The time it takes to get out of the lift - #define PEOPLESPEED 10000 // The maximum time a person spends on a floor + #define LIFTSPEED 500 // The time it takes for the lift to move one floor + #define GETINSPEED 250 // The time it takes to get into the lift + #define GETOUTSPEED 250 // The time it takes to get out of the lift + #define PEOPLESPEED 10000 // The maximum time a person spends on a floor #elif defined(SLOW) - #define LIFTSPEED 250 // The time it takes for the lift to move one floor - #define GETINSPEED 100 // The time it takes to get into the lift - #define GETOUTSPEED 100 // The time it takes to get out of the lift - #define PEOPLESPEED 100 // The maximum time a person spends on a floor + #define LIFTSPEED 250 // The time it takes for the lift to move one floor + #define GETINSPEED 100 // The time it takes to get into the lift + #define GETOUTSPEED 100 // The time it takes to get out of the lift + #define PEOPLESPEED 100 // The maximum time a person spends on a floor #elif defined(FAST) - #define LIFTSPEED 25 // The time it takes for the lift to move one floor - #define GETINSPEED 10 // The time it takes to get into the lift - #define GETOUTSPEED 10 // The time it takes to get out of the lift - #define PEOPLESPEED 10 // The maximum time a person spends on a floor + #define LIFTSPEED 25 // The time it takes for the lift to move one floor + #define GETINSPEED 10 // The time it takes to get into the lift + #define GETOUTSPEED 10 // The time it takes to get out of the lift + #define PEOPLESPEED 10 // The maximum time a person spends on a floor #elif defined(SUPERFAST) - #define LIFTSPEED 0 // The time it takes for the lift to move one floor - #define GETINSPEED 0 // The time it takes to get into the lift - #define GETOUTSPEED 0 // The time it takes to get out of the lift - #define PEOPLESPEED 1 // The maximum time a person spends on a floor + #define LIFTSPEED 0 // The time it takes for the lift to move one floor + #define GETINSPEED 0 // The time it takes to get into the lift + #define GETOUTSPEED 0 // The time it takes to get out of the lift + #define PEOPLESPEED 1 // The maximum time a person spends on a floor #endif // -------------------------------------------------- @@ -52,63 +52,96 @@ #define UP 1 #define DOWN -1 +// Define the lower-case true so that this compiles directly in Windows (GCC 9.2) +#if defined(_WIN32) || defined(WIN32) +#define true 1 +#endif +// Print the number of people in the lifts & on the floors +//#define POPULATIONS + // -------------------------------------------------- // Information about a floor in the building // -------------------------------------------------- -typedef struct { - int waitingtogoup; // The number of people waiting to go up - int waitingtogodown; // The number of people waiting to go down - semaphore up_arrow; // People going up wait on this - semaphore down_arrow; // People going down wait on this +typedef struct +{ + int waitingtogoup; // The number of people waiting to go up + int waitingtogodown; // The number of people waiting to go down + semaphore up_arrow; // People going up wait on this + semaphore down_arrow; // People going down wait on this semaphore queueInteraction; // People can't all press a button at the same time - // Add a tracker to include how many people are currently moving into/out of a lift. - // These people are still considered to be waiting, but a thread is in the process of loading them - int inprogress_up; - int inprogress_down; } floor_info; // -------------------------------------------------- // Information about a lift // -------------------------------------------------- -typedef struct { - int no; // The lift number (id) - int position; // The floor it is on - int direction; // Which direction it is going (UP/DOWN) - int peopleinlift; // The number of people in the lift - int stops[NFLOORS]; // How many people are going to each floor - semaphore stopsem[NFLOORS]; // People in the lift wait on one of these - // Semaphore stating if a thread is currently loading/unloading someone from the lift - //semaphore loading; - // If the target floor is being selected (only one can press at a time) - //semaphore buttonPress; +typedef struct +{ + int no; // The lift number (id) + int position; // The floor it is on + int direction; // Which direction it is going (UP/DOWN) + int peopleinlift; // The number of people in the lift + int stops[NFLOORS]; // How many people are going to each floor + semaphore stopsem[NFLOORS]; // People in the lift wait on one of these } lift_info; // -------------------------------------------------- // Some global variables // -------------------------------------------------- floor_info floors[NFLOORS]; -lift_info* targetLift[NFLOORS]; +lift_info *targetLift[NFLOORS]; // 2-dimensional array of the lift +semaphore targetLiftSelect[NFLOORS]; // Bound all printing to this semaphore semaphore printSemaphore; +// If printing people counts, int array and semaphore to keep track of them +#ifdef POPULATIONS +semaphore updateFloorCount; +int floorCount[NFLOORS]; +// count of times since value was zero, used to help find a stuck person +int floorCountZeroInc[NFLOORS]; // -------------------------------------------------- // Print a string on the screen at position (x,y) // -------------------------------------------------- -void print_at_xy(int x, int y, const char *s) { +void print_at_xy_fast(int x, int y, const char *s) +{ // Lock our print to just one thread (stops x,y from changing) semaphore_wait(&printSemaphore); // Move cursor to (x,y) - gotoxy(x,y); - + gotoxy(x, y); + // Slow things down Sleep(0); // Print the string printf("%s", s); - + // Move cursor out of the way - gotoxy(42, NFLOORS+2); + gotoxy(42, NFLOORS + 2); + // flush the stream and release the semaphore + fflush(stdout); + semaphore_signal(&printSemaphore); +} +#endif + +// -------------------------------------------------- +// Print a string on the screen at position (x,y) +// -------------------------------------------------- +void print_at_xy(int x, int y, const char *s) +{ + // Lock our print to just one thread (stops x,y from changing) + semaphore_wait(&printSemaphore); + // Move cursor to (x,y) + gotoxy(x, y); + + // Slow things down + Sleep(1); + + // Print the string + printf("%s", s); + + // Move cursor out of the way + gotoxy(42, NFLOORS + 2); // flush the stream and release the semaphore fflush(stdout); semaphore_signal(&printSemaphore); @@ -118,69 +151,65 @@ void print_at_xy(int x, int y, const char *s) { // Function for a lift to pick people waiting on a // floor going in a certain direction // -------------------------------------------------- -void get_into_lift(lift_info *lift, int direction) { +void get_into_lift(lift_info *lift, int direction) +{ // Local variables int *waiting; - int *inprogress; semaphore *s; // Check lift direction - if(direction==UP) { + if (direction == UP) + { // Use up_arrow semaphore s = &floors[lift->position].up_arrow; // Number of people waiting to go up waiting = &floors[lift->position].waitingtogoup; - inprogress = &floors[lift->position].inprogress_up; - } else { + } + else + { // Use down_arrow semaphore s = &floors[lift->position].down_arrow; // Number of people waiting to go down waiting = &floors[lift->position].waitingtogodown; - inprogress = &floors[lift->position].inprogress_down; } - // Problems here are primarily state consistency. Between the start of the conditional, the number of waiting people can change, resulting + // Problems here are primarily state consistency. Between the start of the conditional, the number of waiting people can change, resulting // in the number of waiting people dropping below zero. // For all the people waiting - while(*waiting) { + while (*waiting) + { // Check if lift is empty - if(lift->peopleinlift == 0) { + if (lift->peopleinlift == 0) + { // Set the direction of the lift lift->direction = direction; } - + // Check there are people waiting and lift isn't full. Ignore in-progress (moving into lift) people // must check here semaphore_wait(&floors[lift->position].queueInteraction); - if(lift->peopleinlift < MAXNOINLIFT && *waiting - *inprogress) { - //volatile int pos = floors[lift->position].waitingtogodown + floors[lift->position].waitingtogoup - (*inprogress); - (*inprogress)++; - //semaphore_signal(&floors[lift->position].queueInteraction); + if (lift->peopleinlift < MAXNOINLIFT && *waiting) + { // Add person to the lift lift->peopleinlift++; - print_at_xy(NLIFTS*4+floors[lift->position].waitingtogodown + floors[lift->position].waitingtogoup, NFLOORS-lift->position, " "); - // Capture the person's printed position while we have the - //semaphore_signal(&floors[lift->position].queueInteraction); - // Do the print, no need to hold the semaphore while this is going on - - // One less person waiting - // Note that while loading, the queue cannot change - //semaphore_wait(&floors[lift->position].queueInteraction); - + print_at_xy(NLIFTS * 4 + floors[lift->position].waitingtogodown + floors[lift->position].waitingtogoup, NFLOORS - lift->position, " "); + (*waiting)--; - (*inprogress)--; semaphore_signal(&floors[lift->position].queueInteraction); - // Wait for person to get into lift Sleep(GETINSPEED); // Need a sem here + // Wait til we can be the lift that is loading + semaphore_wait(&targetLiftSelect[lift->position]); targetLift[lift->position] = lift; semaphore_signal(s); - } else { - semaphore_signal(&floors[lift->position].queueInteraction); + } + else + { + semaphore_signal(&floors[lift->position].queueInteraction); break; } } @@ -189,24 +218,26 @@ void get_into_lift(lift_info *lift, int direction) { // -------------------------------------------------- // Function for the Lift Threads // -------------------------------------------------- -void* lift_thread(void *p) { +void *lift_thread(void *p) +{ // Local variables lift_info lift; int no = (long long)p; int i; - + // Set up Lift - lift.no = no; // Set lift number - lift.position = 0; // Lift starts on ground floor - lift.direction = UP; // Lift starts going up - lift.peopleinlift = 0; // Lift starts empty + lift.no = no; // Set lift number + lift.position = 0; // Lift starts on ground floor + lift.direction = UP; // Lift starts going up + lift.peopleinlift = 0; // Lift starts empty // lift is ok with loading a single person //semaphore_create(&lift.loading, 1); //semaphore_create(&lift.buttonPress, 1); - for(i = 0; i < NFLOORS; i++) { - lift.stops[i]=0; // No passengers waiting - semaphore_create(&lift.stopsem[i], 0); // Initialise semaphores + for (i = 0; i < NFLOORS; i++) + { + lift.stops[i] = 0; // No passengers waiting + semaphore_create(&lift.stopsem[i], 0); // Initialise semaphores } // Randomise lift @@ -216,162 +247,190 @@ void* lift_thread(void *p) { Sleep(rnd(1000)); // Loop forever - while(true) { + while (true) + { // Print current position of the lift - print_at_xy(no*4+1, NFLOORS-lift.position, lf); + print_at_xy(no * 4 + 1, NFLOORS - lift.position, lf); // Wait for a while Sleep(LIFTSPEED); + // Print the number of people in the lift +#ifdef POPULATIONS + char str[12]; + sprintf(str, "%d", lift.peopleinlift); + print_at_xy_fast(no * 4 + 1, NFLOORS + 5, " "); + print_at_xy_fast(no * 4 + 1, NFLOORS + 5, str); +#endif + // Drop off passengers on this floor - while (lift.stops[lift.position] != 0) { + while (lift.stops[lift.position] != 0) + { // One less passenger in lift - //semaphore_wait(&lift.loading); lift.peopleinlift--; - //semaphore_signal(&lift.loading); + // One less waiting to get off at this floor - // Don't need a semaphore as nothing should read this value now - //semaphore_wait(&lift.buttonPress); lift.stops[lift.position]--; - //semaphore_signal(&lift.buttonPress); - + // Wait for exit lift delay Sleep(GETOUTSPEED); - + + // Signal passenger to leave lift semaphore_signal(&lift.stopsem[lift.position]); - // Signal passenger to leave lift + // Check if that was the last passenger waiting for this floor - if(!lift.stops[lift.position]) { + if (!lift.stops[lift.position]) + { // Clear the "-" - print_at_xy(no*4+1+2, NFLOORS-lift.position, " "); - + print_at_xy(no * 4 + 1 + 2, NFLOORS - lift.position, " "); } } // Check if lift is going up or is empty - if(lift.direction==UP || !lift.peopleinlift) { + if (lift.direction == UP || !lift.peopleinlift) + { // Pick up passengers waiting to go up get_into_lift(&lift, UP); } // Check if lift is going down or is empty - if(lift.direction==DOWN || !lift.peopleinlift) { + if (lift.direction == DOWN || !lift.peopleinlift) + { // Pick up passengers waiting to go down get_into_lift(&lift, DOWN); } - + // Erase lift from screen - print_at_xy(no*4+1, NFLOORS-lift.position, (lift.direction + 1 ? " " : lc)); + print_at_xy(no * 4 + 1, NFLOORS - lift.position, (lift.direction + 1 ? " " : lc)); // Move lift lift.position += lift.direction; // Check if lift is at top or bottom - if(lift.position == 0 || lift.position == NFLOORS-1) { + if (lift.position == 0 || lift.position == NFLOORS - 1) + { // Change lift direction lift.direction = -lift.direction; } } - + return NULL; } // -------------------------------------------------- // Function for the Person Threads // -------------------------------------------------- -void* person_thread(void *p) { +void *person_thread(void *p) +{ // Local variables int from = 0, to; // Start on the ground floor lift_info *lift; - // Randomise randomise(); // Stay in the building forever - while(true) { + while (true) + { // Work for a while Sleep(rnd(PEOPLESPEED)); - do { + do + { // Randomly pick another floor to go to to = rnd(NFLOORS); - } while(to == from); - semaphore* s; - // Wait for our turn to press a button - + } while (to == from); + semaphore *s; // Check which direction the person is going (UP/DOWN) - if(to > from) { + if (to > from) + { // One more person waiting to go up semaphore_wait(&floors[from].queueInteraction); floors[from].waitingtogoup++; - //volatile int pos = floors[from].waitingtogoup +floors[from].waitingtogodown - floors[from].inprogress_down - floors[from].inprogress_up; - print_at_xy(NLIFTS*4+ floors[from].waitingtogoup +floors[from].waitingtogodown,NFLOORS-from, pr); + print_at_xy(NLIFTS * 4 + floors[from].waitingtogoup + floors[from].waitingtogodown, NFLOORS - from, pr); semaphore_signal(&floors[from].queueInteraction); // Print person waiting - + s = &floors[from].up_arrow; // Wait for a lift to arrive (going up) - } else { + } + else + { semaphore_wait(&floors[from].queueInteraction); // One more person waiting to go down floors[from].waitingtogodown++; - //volatile int pos = floors[from].waitingtogoup +floors[from].waitingtogodown - floors[from].inprogress_down - floors[from].inprogress_up; - print_at_xy(NLIFTS*4+floors[from].waitingtogoup +floors[from].waitingtogodown,NFLOORS-from, pr); + print_at_xy(NLIFTS * 4 + floors[from].waitingtogoup + floors[from].waitingtogodown, NFLOORS - from, pr); semaphore_signal(&floors[from].queueInteraction); // Print person waiting // We want this to happen after the semaphore is released, so the person is added after any deletions - + s = &floors[from].down_arrow; // Wait for a lift to arrive (going down) } // We've pressed our button - + semaphore_wait(s); - + // Which lift we are getting into lift = targetLift[from]; - + // Realease the target-lift semaphore + semaphore_signal(&targetLiftSelect[lift->position]); // Add one to passengers waiting for floor - // Only one person enters at a time - //semaphore_wait(&lift->buttonPress); lift->stops[to]++; - //semaphore_signal(&lift->buttonPress); + // Press button if we are the first - if(lift->stops[to]==1) { + if (lift->stops[to] == 1) + { // Print light for destination - print_at_xy(lift->no*4+1+2, NFLOORS-to, "-"); + print_at_xy(lift->no * 4 + 1 + 2, NFLOORS - to, "-"); } semaphore_wait(&lift->stopsem[to]); // Wait until we are at the right floor + +#ifdef POPULATIONS + semaphore_wait(&updateFloorCount); + floorCount[to]++; + floorCount[from]--; + semaphore_signal(&updateFloorCount); + // Print the current person's floor + char str[3]; + sprintf(str, "%d", to); + print_at_xy_fast((long long)p * 4 + 1, NFLOORS + 8, " "); + print_at_xy_fast((long long)p * 4 + 1, NFLOORS + 8, str); +#endif // Exit the lift from = to; } - + return NULL; } // -------------------------------------------------- // Print the building on the screen // -------------------------------------------------- -void printbuilding(void) { +void printbuilding(void) +{ // Local variables - int l,f; + int l, f; // Clear Screen system(clear_screen); // Print the whole building before anything else // Print Roof printf("%s", tl); - for(l = 0; l < NLIFTS-1; l++) { + for (l = 0; l < NLIFTS - 1; l++) + { printf("%s%s%s%s", hl, td, hl, td); } printf("%s%s%s%s\n", hl, td, hl, tr); - + // Print Floors and Lifts - for(f = NFLOORS-1; f >= 0; f--) { - for(l = 0; l < NLIFTS; l++) { + for (f = NFLOORS - 1; f >= 0; f--) + { + for (l = 0; l < NLIFTS; l++) + { printf("%s%s%s ", vl, lc, vl); - if(l == NLIFTS-1) { + if (l == NLIFTS - 1) + { printf("%s\n", vl); } } @@ -379,75 +438,133 @@ void printbuilding(void) { // Print Ground printf("%s", bl); - for(l = 0; l < NLIFTS-1; l++) { + for (l = 0; l < NLIFTS - 1; l++) + { printf("%s%s%s%s", hl, tu, hl, tu); } printf("%s%s%s%s\n", hl, tu, hl, br); // Print Message printf("Lift Simulation - Press CTRL-Break to exit\n"); + +#ifdef POPULATIONS + gotoxy(0, NFLOORS + 7); + printf("People\'s Destination Floors:"); + gotoxy(0, NFLOORS + 4); + printf("Lift Occupants:"); + gotoxy(4 * NLIFTS + NPEOPLE + 5, 0); + printf("Number of People on Floor:"); +#endif // Ensure buffer is written fflush(stdout); // Once the building has been printed, then we can those waiting to print that they may do so semaphore_signal(&printSemaphore); } + +#ifdef POPULATIONS // -------------------------------------------------- // Iterate through the floors and update the queue size // -------------------------------------------------- -void* update_floor_counts(void *p){ - while(true){ - int i; - for (i = 0; i < NFLOORS; i++){ - char str[12]; - sprintf(str, "%d", floors[i].waitingtogodown + floors[i].waitingtogoup); - print_at_xy(4*NLIFTS+NPEOPLE, NFLOORS-i, " "); - print_at_xy(4*NLIFTS+NPEOPLE, NFLOORS-i, str); +void *update_floor_counts(void *p) +{ + int i; + int k; + char str2[17] = {';',' ', 'i', 't', 'e', 'r', 's', ' ', 's', 'i', 'n', 'c', 'e', ' ', '0', ':', ' '}; + while (true) + { + for (i = -1; i < NFLOORS; i++) + { + char str[48]; + char str3[12]; + if (i != -1) + { + if (floorCount[i] != 0){ + floorCountZeroInc[i]++; + } + else{ + floorCountZeroInc[i] = 0; + } + sprintf(str, "%d", floorCount[i]); + sprintf(str3, "%d", floorCountZeroInc[i]); + strcat(str, str2); + strcat(str, str3); + print_at_xy_fast(4 * NLIFTS + NPEOPLE + 5, NFLOORS - i, " "); + print_at_xy_fast(4 * NLIFTS + NPEOPLE + 5, NFLOORS - i, str); + } + else + { + int ttl = 0; + for (k = 0; k < NFLOORS; k++) + { + ttl += floorCount[k]; + } + sprintf(str, "%d", ttl); + if (ttl != NPEOPLE) + { + break; + } + print_at_xy_fast(4 * NLIFTS + NPEOPLE + 5, NFLOORS - i, str); + } + } - } Sleep(0); - } +#endif // -------------------------------------------------- // Main starts the threads and then waits. // -------------------------------------------------- -int main() { +int main() +{ // Local variables unsigned long i; semaphore_create(&printSemaphore, 0); // Initialise Building - for(i = 0; i < NFLOORS; i++) { - // Initialise Floor - floors[i].inprogress_down = 0; - floors[i].inprogress_up = 0; + for (i = 0; i < NFLOORS; i++) + { floors[i].waitingtogoup = 0; floors[i].waitingtogodown = 0; semaphore_create(&floors[i].up_arrow, 0); semaphore_create(&floors[i].down_arrow, 0); semaphore_create(&floors[i].queueInteraction, 1); // This initially has one available button press + semaphore_create(&targetLiftSelect[i], 1); // This initially has one available button press +#ifdef POPULATIONS + if (i == 0) + { + semaphore_create(&updateFloorCount, 1); // Moved, to save excessive preprocessor tags + floorCount[0] = NPEOPLE; + floorCountZeroInc[0] = 0; + } + else + { + floorCount[i] = 0; + floorCountZeroInc[i] = 0; + } +#endif } - // --- Initialise any other semaphores --- - + // Print Building printbuilding(); // Create Lifts - for(i = 0; i < NLIFTS; i++) { + for (i = 0; i < NLIFTS; i++) + { // Create Lift Thread - create_thread(lift_thread, (void*)i); + create_thread(lift_thread, (void *)i); } // Create People - for(i = 0; i < NPEOPLE; i++) { + for (i = 0; i < NPEOPLE; i++) + { // Create Person Thread - create_thread(person_thread, (void*)i); + create_thread(person_thread, (void *)i); } - //create_thread(update_floor_counts, (void*)i); +#ifdef POPULATIONS + create_thread(update_floor_counts, (void *)i); +#endif // Go to sleep for 86400 seconds (one day) Sleep(86400000ULL); } - -