2021-05-01 13:56:12 +12:00
/* Dempsey-Jensen, Brychan, 14299890, Assignment 2, 159.341 */
/* Use semaphores to prevent race conditions in a concurrent lift-simulator */
2021-04-21 14:25:20 +12:00
// --------------------------------------------------
// --- 159.341 Assignment 2 - Lift Simulator ---
// --------------------------------------------------
// Written by M. J. Johnson
// Updated by D. P. Playne - 2019
# include <stdio.h>
# include <stddef.h>
# include <stdlib.h>
# include "lift.h"
// --------------------------------------------------
// Define Problem Size
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
# 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
2021-04-21 14:25:20 +12:00
// --------------------------------------------------
// Define delay times (in milliseconds)
// --------------------------------------------------
2021-04-27 20:34:24 +12:00
//#define SUPERSLOW
//#define SLOW
2021-04-30 15:15:14 +12:00
//#define FAST
# define SUPERFAST
2021-04-27 20:34:24 +12:00
# if defined(SUPERSLOW)
2021-04-30 15:15:14 +12:00
# 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
2021-04-27 20:34:24 +12:00
# elif defined(SLOW)
2021-04-30 15:15:14 +12:00
# 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
2021-04-21 14:25:20 +12:00
# elif defined(FAST)
2021-04-30 15:15:14 +12:00
# 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
2021-04-27 20:34:24 +12:00
# elif defined(SUPERFAST)
2021-04-30 15:15:14 +12:00
# 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
2021-04-21 14:25:20 +12:00
# endif
// --------------------------------------------------
// Define lift directions (UP/DOWN)
// --------------------------------------------------
# define UP 1
# define DOWN -1
2021-04-30 15:15:14 +12:00
// Define the lower-case true so that this compiles directly in Windows (GCC 9.2)
# if defined(_WIN32) || defined(WIN32)
2021-04-30 20:43:17 +12:00
# define true TRUE
2021-04-30 15:15:14 +12:00
# endif
// Print the number of people in the lifts & on the floors
2021-04-30 17:38:44 +12:00
//#define POPULATIONS
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// --------------------------------------------------
// Information about a floor in the building
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
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
2021-04-27 17:08:11 +12:00
semaphore queueInteraction ; // People can't all press a button at the same time
2021-04-21 14:25:20 +12:00
} floor_info ;
// --------------------------------------------------
// Information about a lift
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
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
2021-04-30 16:57:45 +12:00
semaphore addToStop ;
2021-04-21 14:25:20 +12:00
} lift_info ;
// --------------------------------------------------
// Some global variables
// --------------------------------------------------
floor_info floors [ NFLOORS ] ;
2021-04-30 15:15:14 +12:00
lift_info * targetLift [ NFLOORS ] ; // 2-dimensional array of the lift
semaphore targetLiftSelect [ NFLOORS ] ;
2021-04-27 17:08:11 +12:00
// Bound all printing to this semaphore
semaphore printSemaphore ;
2021-04-30 15:15:14 +12:00
// 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 ] ;
2021-04-21 14:25:20 +12:00
// --------------------------------------------------
// Print a string on the screen at position (x,y)
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void print_at_xy_fast ( int x , int y , const char * s )
{
2021-04-27 20:34:24 +12:00
// Lock our print to just one thread (stops x,y from changing)
2021-04-27 17:08:11 +12:00
semaphore_wait ( & printSemaphore ) ;
2021-04-21 14:25:20 +12:00
// Move cursor to (x,y)
2021-04-30 15:15:14 +12:00
gotoxy ( x , y ) ;
2021-04-21 14:25:20 +12:00
// Slow things down
2021-04-30 17:38:44 +12:00
Sleep ( 0 ) ;
2021-04-21 14:25:20 +12:00
// Print the string
printf ( " %s " , s ) ;
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Move cursor out of the way
2021-04-30 15:15:14 +12:00
gotoxy ( 42 , NFLOORS + 2 ) ;
// flush the stream and release the semaphore
2021-04-30 17:38:44 +12:00
//fflush(stdout);
2021-04-30 15:15:14 +12:00
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
2021-04-30 17:38:44 +12:00
Sleep ( 1 ) ;
2021-04-30 15:15:14 +12:00
// Print the string
printf ( " %s " , s ) ;
// Move cursor out of the way
gotoxy ( 42 , NFLOORS + 2 ) ;
2021-04-27 20:34:24 +12:00
// flush the stream and release the semaphore
2021-04-30 17:38:44 +12:00
//fflush(stdout);
2021-04-27 17:08:11 +12:00
semaphore_signal ( & printSemaphore ) ;
2021-04-21 14:25:20 +12:00
}
// --------------------------------------------------
// Function for a lift to pick people waiting on a
// floor going in a certain direction
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void get_into_lift ( lift_info * lift , int direction )
{
2021-04-21 14:25:20 +12:00
// Local variables
2021-04-27 20:48:52 +12:00
int * waiting ;
2021-04-21 14:25:20 +12:00
semaphore * s ;
// Check lift direction
2021-04-30 15:15:14 +12:00
if ( direction = = UP )
{
2021-04-21 14:25:20 +12:00
// Use up_arrow semaphore
s = & floors [ lift - > position ] . up_arrow ;
// Number of people waiting to go up
waiting = & floors [ lift - > position ] . waitingtogoup ;
2021-04-30 15:15:14 +12:00
}
else
{
2021-04-21 14:25:20 +12:00
// Use down_arrow semaphore
s = & floors [ lift - > position ] . down_arrow ;
// Number of people waiting to go down
waiting = & floors [ lift - > position ] . waitingtogodown ;
}
2021-04-30 15:15:14 +12:00
// Problems here are primarily state consistency. Between the start of the conditional, the number of waiting people can change, resulting
2021-04-27 20:34:24 +12:00
// in the number of waiting people dropping below zero.
2021-04-21 14:25:20 +12:00
// For all the people waiting
2021-04-30 15:15:14 +12:00
while ( * waiting )
{
2021-04-21 14:25:20 +12:00
// Check if lift is empty
2021-04-30 15:15:14 +12:00
if ( lift - > peopleinlift = = 0 )
{
2021-04-21 14:25:20 +12:00
// Set the direction of the lift
lift - > direction = direction ;
}
2021-04-30 15:15:14 +12:00
2021-04-27 20:34:24 +12:00
// 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 ) ;
2021-04-30 15:15:14 +12:00
if ( lift - > peopleinlift < MAXNOINLIFT & & * waiting )
{
2021-04-21 14:25:20 +12:00
// Add person to the lift
lift - > peopleinlift + + ;
2021-04-30 15:15:14 +12:00
print_at_xy ( NLIFTS * 4 + floors [ lift - > position ] . waitingtogodown + floors [ lift - > position ] . waitingtogoup , NFLOORS - lift - > position , " " ) ;
2021-04-21 14:25:20 +12:00
( * waiting ) - - ;
2021-04-27 20:34:24 +12:00
semaphore_signal ( & floors [ lift - > position ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
// Wait for person to get into lift
Sleep ( GETINSPEED ) ;
2021-04-28 17:54:37 +12:00
// Need a sem here
2021-04-30 15:15:14 +12:00
// Wait til we can be the lift that is loading
semaphore_wait ( & targetLiftSelect [ lift - > position ] ) ;
2021-04-27 17:08:11 +12:00
targetLift [ lift - > position ] = lift ;
2021-04-30 16:57:45 +12:00
// lock the addtostop
semaphore_wait ( & lift - > addToStop ) ;
2021-04-27 17:08:11 +12:00
semaphore_signal ( s ) ;
2021-04-30 15:15:14 +12:00
}
else
{
semaphore_signal ( & floors [ lift - > position ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
break ;
}
}
}
// --------------------------------------------------
// Function for the Lift Threads
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void * lift_thread ( void * p )
{
2021-04-21 14:25:20 +12:00
// Local variables
lift_info lift ;
int no = ( long long ) p ;
int i ;
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Set up Lift
2021-04-30 15:15:14 +12:00
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
2021-04-27 20:34:24 +12:00
// lift is ok with loading a single person
2021-04-30 16:57:45 +12:00
semaphore_create ( & lift . addToStop , 1 ) ;
2021-04-28 17:54:37 +12:00
//semaphore_create(&lift.buttonPress, 1);
2021-04-27 17:08:11 +12:00
2021-04-30 15:15:14 +12:00
for ( i = 0 ; i < NFLOORS ; i + + )
{
lift . stops [ i ] = 0 ; // No passengers waiting
semaphore_create ( & lift . stopsem [ i ] , 0 ) ; // Initialise semaphores
2021-04-21 14:25:20 +12:00
}
// Randomise lift
randomise ( ) ;
// Wait for random start up time (up to a second)
Sleep ( rnd ( 1000 ) ) ;
// Loop forever
2021-04-30 15:15:14 +12:00
while ( true )
{
2021-04-21 14:25:20 +12:00
// Print current position of the lift
2021-04-30 15:15:14 +12:00
print_at_xy ( no * 4 + 1 , NFLOORS - lift . position , lf ) ;
2021-04-21 14:25:20 +12:00
// Wait for a while
Sleep ( LIFTSPEED ) ;
2021-04-30 15:15:14 +12:00
// 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
2021-04-21 14:25:20 +12:00
// Drop off passengers on this floor
2021-04-30 15:15:14 +12:00
while ( lift . stops [ lift . position ] ! = 0 )
{
2021-04-30 16:57:45 +12:00
// These are sequential, so don't need protecting
2021-04-21 14:25:20 +12:00
// One less passenger in lift
2021-04-30 16:57:45 +12:00
2021-04-21 14:25:20 +12:00
lift . peopleinlift - - ;
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// One less waiting to get off at this floor
lift . stops [ lift . position ] - - ;
2021-04-30 16:57:45 +12:00
2021-04-21 14:25:20 +12:00
// Wait for exit lift delay
Sleep ( GETOUTSPEED ) ;
2021-04-30 15:15:14 +12:00
// Signal passenger to leave lift
2021-04-27 17:08:11 +12:00
semaphore_signal ( & lift . stopsem [ lift . position ] ) ;
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Check if that was the last passenger waiting for this floor
2021-04-30 15:15:14 +12:00
if ( ! lift . stops [ lift . position ] )
{
2021-04-21 14:25:20 +12:00
// Clear the "-"
2021-04-30 15:15:14 +12:00
print_at_xy ( no * 4 + 1 + 2 , NFLOORS - lift . position , " " ) ;
2021-04-21 14:25:20 +12:00
}
}
// Check if lift is going up or is empty
2021-04-30 15:15:14 +12:00
if ( lift . direction = = UP | | ! lift . peopleinlift )
{
2021-04-21 14:25:20 +12:00
// Pick up passengers waiting to go up
get_into_lift ( & lift , UP ) ;
}
// Check if lift is going down or is empty
2021-04-30 15:15:14 +12:00
if ( lift . direction = = DOWN | | ! lift . peopleinlift )
{
2021-04-21 14:25:20 +12:00
// Pick up passengers waiting to go down
get_into_lift ( & lift , DOWN ) ;
}
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Erase lift from screen
2021-04-30 15:15:14 +12:00
print_at_xy ( no * 4 + 1 , NFLOORS - lift . position , ( lift . direction + 1 ? " " : lc ) ) ;
2021-04-21 14:25:20 +12:00
// Move lift
2021-04-30 16:57:45 +12:00
// Hold the lift while someone is being added, before moving off
// this really could go anywhere, but it fits the metaphor to wrap it here (doesn't need to wrap anything)
semaphore_wait ( & lift . addToStop ) ;
2021-04-21 14:25:20 +12:00
lift . position + = lift . direction ;
2021-04-30 16:57:45 +12:00
semaphore_signal ( & lift . addToStop ) ;
2021-04-21 14:25:20 +12:00
// Check if lift is at top or bottom
2021-04-30 15:15:14 +12:00
if ( lift . position = = 0 | | lift . position = = NFLOORS - 1 )
{
2021-04-21 14:25:20 +12:00
// Change lift direction
lift . direction = - lift . direction ;
}
}
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
return NULL ;
}
// --------------------------------------------------
// Function for the Person Threads
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void * person_thread ( void * p )
{
2021-04-21 14:25:20 +12:00
// Local variables
int from = 0 , to ; // Start on the ground floor
lift_info * lift ;
// Randomise
randomise ( ) ;
// Stay in the building forever
2021-04-30 15:15:14 +12:00
while ( true )
{
2021-04-21 14:25:20 +12:00
// Work for a while
Sleep ( rnd ( PEOPLESPEED ) ) ;
2021-04-30 15:15:14 +12:00
do
{
2021-04-21 14:25:20 +12:00
// Randomly pick another floor to go to
to = rnd ( NFLOORS ) ;
2021-04-30 15:15:14 +12:00
} while ( to = = from ) ;
semaphore * s ;
2021-04-21 14:25:20 +12:00
// Check which direction the person is going (UP/DOWN)
2021-04-30 15:15:14 +12:00
if ( to > from )
{
2021-04-21 14:25:20 +12:00
// One more person waiting to go up
2021-04-28 17:54:37 +12:00
semaphore_wait ( & floors [ from ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
floors [ from ] . waitingtogoup + + ;
2021-04-30 15:15:14 +12:00
print_at_xy ( NLIFTS * 4 + floors [ from ] . waitingtogoup + floors [ from ] . waitingtogodown , NFLOORS - from , pr ) ;
2021-04-27 17:08:11 +12:00
semaphore_signal ( & floors [ from ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
// Print person waiting
2021-04-30 15:15:14 +12:00
2021-04-27 17:08:11 +12:00
s = & floors [ from ] . up_arrow ;
// Wait for a lift to arrive (going up)
2021-04-30 15:15:14 +12:00
}
else
{
2021-04-28 17:54:37 +12:00
semaphore_wait ( & floors [ from ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
// One more person waiting to go down
floors [ from ] . waitingtogodown + + ;
2021-04-30 15:15:14 +12:00
print_at_xy ( NLIFTS * 4 + floors [ from ] . waitingtogoup + floors [ from ] . waitingtogodown , NFLOORS - from , pr ) ;
2021-04-27 17:08:11 +12:00
semaphore_signal ( & floors [ from ] . queueInteraction ) ;
2021-04-21 14:25:20 +12:00
// Print person waiting
2021-04-27 20:34:24 +12:00
// We want this to happen after the semaphore is released, so the person is added after any deletions
2021-04-30 15:15:14 +12:00
2021-04-27 17:08:11 +12:00
s = & floors [ from ] . down_arrow ;
// Wait for a lift to arrive (going down)
2021-04-21 14:25:20 +12:00
}
2021-04-27 17:08:11 +12:00
// We've pressed our button
2021-04-30 16:57:45 +12:00
// waiting for a lift's doors to open
2021-04-27 17:08:11 +12:00
semaphore_wait ( s ) ;
2021-04-30 16:57:45 +12:00
// Which lift we are getting into. The targetLift has locked the variable, so once we have our reference,
2021-04-27 17:08:11 +12:00
lift = targetLift [ from ] ;
2021-04-30 16:57:45 +12:00
// Realease the targetLift ASAP so another lift can load someone
2021-04-30 15:15:14 +12:00
semaphore_signal ( & targetLiftSelect [ lift - > position ] ) ;
2021-04-30 16:57:45 +12:00
// GetIntoLift() continues its loop, from here (this passenger is signalled to enter; so we definitely need to hold a lock around
// this value)
// When GetIntoLift() decides that a passenger should enter, it obtains a lock of addToStop.
// We release that lock here. Finally, once all passengers have been picked up and the lift decides to move on, if this lock is
// still held, then the lift wont change floor (protecting against unloading issues)
2021-04-30 15:15:14 +12:00
2021-04-30 16:57:45 +12:00
// We could do this by extending the targetLiftSelect semaphore through the same condition, but that would affect the performance of all lifts on this floor
lift - > stops [ to ] + + ;
semaphore_signal ( & lift - > addToStop ) ;
2021-04-21 14:25:20 +12:00
// Press button if we are the first
2021-04-30 16:57:45 +12:00
// Technically, the semaphore should extend through this conditional, but as it is only a read operation whose state is should to
// be greater than 0 here, it doesn't significantly matter to overwrite the char again (the performance impact is low)
2021-04-30 15:15:14 +12:00
if ( lift - > stops [ to ] = = 1 )
{
2021-04-21 14:25:20 +12:00
// Print light for destination
2021-04-30 15:15:14 +12:00
print_at_xy ( lift - > no * 4 + 1 + 2 , NFLOORS - to , " - " ) ;
2021-04-21 14:25:20 +12:00
}
2021-04-27 17:08:11 +12:00
semaphore_wait ( & lift - > stopsem [ to ] ) ;
// Wait until we are at the right floor
2021-04-21 14:25:20 +12:00
2021-04-30 15:15:14 +12:00
# 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
2021-04-21 14:25:20 +12:00
// Exit the lift
from = to ;
}
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
return NULL ;
}
// --------------------------------------------------
// Print the building on the screen
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void printbuilding ( void )
{
2021-04-27 17:08:11 +12:00
2021-04-21 14:25:20 +12:00
// Local variables
2021-04-30 15:15:14 +12:00
int l , f ;
2021-04-21 14:25:20 +12:00
// Clear Screen
system ( clear_screen ) ;
2021-04-27 17:08:11 +12:00
// Print the whole building before anything else
2021-04-21 14:25:20 +12:00
// Print Roof
printf ( " %s " , tl ) ;
2021-04-30 15:15:14 +12:00
for ( l = 0 ; l < NLIFTS - 1 ; l + + )
{
2021-04-21 14:25:20 +12:00
printf ( " %s%s%s%s " , hl , td , hl , td ) ;
}
printf ( " %s%s%s%s \n " , hl , td , hl , tr ) ;
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Print Floors and Lifts
2021-04-30 15:15:14 +12:00
for ( f = NFLOORS - 1 ; f > = 0 ; f - - )
{
for ( l = 0 ; l < NLIFTS ; l + + )
{
2021-04-21 14:25:20 +12:00
printf ( " %s%s%s " , vl , lc , vl ) ;
2021-04-30 15:15:14 +12:00
if ( l = = NLIFTS - 1 )
{
2021-04-21 14:25:20 +12:00
printf ( " %s \n " , vl ) ;
}
}
}
// Print Ground
printf ( " %s " , bl ) ;
2021-04-30 15:15:14 +12:00
for ( l = 0 ; l < NLIFTS - 1 ; l + + )
{
2021-04-21 14:25:20 +12:00
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 " ) ;
2021-04-30 15:15:14 +12:00
# 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
2021-04-27 17:08:11 +12:00
// Ensure buffer is written
fflush ( stdout ) ;
2021-04-27 20:34:24 +12:00
// Once the building has been printed, then we can those waiting to print that they may do so
2021-04-27 17:08:11 +12:00
semaphore_signal ( & printSemaphore ) ;
2021-04-21 14:25:20 +12:00
}
2021-04-30 15:15:14 +12:00
# ifdef POPULATIONS
2021-04-27 20:34:24 +12:00
// --------------------------------------------------
// Iterate through the floors and update the queue size
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
void * update_floor_counts ( void * p )
{
int i ;
int k ;
2021-04-30 16:57:45 +12:00
char str2 [ 18 ] = { ' ; ' , ' ' , ' \t ' , ' i ' , ' t ' , ' e ' , ' r ' , ' s ' , ' ' , ' s ' , ' i ' , ' n ' , ' c ' , ' e ' , ' ' , ' 0 ' , ' : ' , ' ' } ;
2021-04-30 15:15:14 +12:00
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 ) ;
2021-04-30 16:57:45 +12:00
print_at_xy_fast ( 4 * NLIFTS + NPEOPLE + 5 , NFLOORS - i , " " ) ;
2021-04-30 15:15:14 +12:00
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 ) ;
}
2021-04-27 20:34:24 +12:00
}
}
2021-04-30 17:38:44 +12:00
//Sleep(0);
2021-04-27 20:34:24 +12:00
}
2021-04-30 15:15:14 +12:00
# endif
2021-04-27 20:34:24 +12:00
2021-04-21 14:25:20 +12:00
// --------------------------------------------------
// Main starts the threads and then waits.
// --------------------------------------------------
2021-04-30 15:15:14 +12:00
int main ( )
{
2021-05-01 13:56:12 +12:00
// Intro stage:
printf ( " |------------------------------------------| \n " ) ;
printf ( " | 159.341 2021 Semester 1, Assignment 2 | \n " ) ;
printf ( " | Submitted by Brychan Dempsey, 14299890 | \n " ) ;
printf ( " |------------------------------------------| \n " ) ;
printf ( " \n Press \' enter \' to begin. " ) ;
char c ;
do {
c = getchar ( ) ;
//putchar (c);
} while ( ! ( c = = 10 | | c = = 12 ) ) ;
2021-04-21 14:25:20 +12:00
// Local variables
unsigned long i ;
2021-04-27 20:34:24 +12:00
semaphore_create ( & printSemaphore , 0 ) ;
2021-04-21 14:25:20 +12:00
// Initialise Building
2021-04-30 15:15:14 +12:00
for ( i = 0 ; i < NFLOORS ; i + + )
{
2021-04-21 14:25:20 +12:00
floors [ i ] . waitingtogoup = 0 ;
floors [ i ] . waitingtogodown = 0 ;
semaphore_create ( & floors [ i ] . up_arrow , 0 ) ;
semaphore_create ( & floors [ i ] . down_arrow , 0 ) ;
2021-04-27 17:08:11 +12:00
semaphore_create ( & floors [ i ] . queueInteraction , 1 ) ; // This initially has one available button press
2021-04-30 15:15:14 +12:00
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
2021-04-21 14:25:20 +12:00
}
// --- Initialise any other semaphores ---
2021-04-30 15:15:14 +12:00
2021-04-21 14:25:20 +12:00
// Print Building
printbuilding ( ) ;
// Create Lifts
2021-04-30 15:15:14 +12:00
for ( i = 0 ; i < NLIFTS ; i + + )
{
2021-04-21 14:25:20 +12:00
// Create Lift Thread
2021-04-30 15:15:14 +12:00
create_thread ( lift_thread , ( void * ) i ) ;
2021-04-21 14:25:20 +12:00
}
// Create People
2021-04-30 15:15:14 +12:00
for ( i = 0 ; i < NPEOPLE ; i + + )
{
2021-04-21 14:25:20 +12:00
// Create Person Thread
2021-04-30 15:15:14 +12:00
create_thread ( person_thread , ( void * ) i ) ;
2021-04-21 14:25:20 +12:00
}
2021-04-30 15:15:14 +12:00
# ifdef POPULATIONS
create_thread ( update_floor_counts , ( void * ) i ) ;
# endif
2021-04-21 14:25:20 +12:00
// Go to sleep for 86400 seconds (one day)
Sleep ( 86400000ULL ) ;
}