#include // for pthread_create(), pthread_join(), etc. #include // for scanf(), printf(), etc. #include // for malloc() #include // for sleep() #define NUMBER_OF_BOXES_PER_DWELLER 5 #define ROOM_IN_TRUCK 10 #define MIN_BOX_WEIGHT 5 #define MAX_BOX_WEIGHT 50 #define MAX_TIME_FOR_HOUSE_DWELLER 7 #define MIN_TIME_FOR_HOUSE_DWELLER 1 #define MAX_TIME_FOR_MOVER 3 #define MIN_TIME_FOR_MOVER 1 #define MIN_TIME_FOR_TRUCKER 1 #define MAX_TIME_FOR_TRUCKER 3 #define MIN_TRIP_TIME 5 #define MAX_TRIP_TIME 10 #define RANDOM_WITHIN_RANGE(a, b, seed) (a+rand_r(&seed)%(b-a)) // For pipes #define READ_END 0 #define WRITE_END 1 // Pipe between house dwellers and movers int houseFloor[2]; // Pipe between movers and truckers int nextToTrucks[2]; //TODO: See if you can just use arg structure instead of making stack vars from the args // Arg structure, need to assign id in loop, and a reference to a seed for rand_r(), since it mutates the seed typedef struct args { int id; unsigned int seed; } Args; // Routine for house dwellers void *dweller(void *arg) { Args *args = (Args *) arg; // Cast void* to Args*, as pthread_create() requires void* int id = args->id; unsigned int seed = args->seed; printf("Hello from house dweller %d\n", id); for (int i = 0; i < NUMBER_OF_BOXES_PER_DWELLER; i++) { int weight = RANDOM_WITHIN_RANGE(MIN_BOX_WEIGHT, MAX_BOX_WEIGHT, seed); // Generate random weight int time = RANDOM_WITHIN_RANGE(MIN_TIME_FOR_HOUSE_DWELLER, MAX_TIME_FOR_HOUSE_DWELLER, seed); // Time to pack box sleep(time); // Simulate packing time write(houseFloor[WRITE_END], &weight, sizeof(int)); // Write weight to pipe printf("House dweller %d created a box that weights %d in %d units of time\n", id, weight, time); } printf("House dweller %d is done packing\n", id); free(args); // Make sure to free the args struct return NULL; } // Routine for movers // Comments from dweller() apply here as well void *mover(void *arg) { Args *args = (Args *) arg; int id = args->id; unsigned int seed = args->seed; int weight; printf("Hello from mover %d\n", id); while (read(houseFloor[READ_END], &weight, sizeof(int)) > 0) { // Read from pipe, until dwellers are all done int time = RANDOM_WITHIN_RANGE(MIN_TIME_FOR_MOVER, MAX_TIME_FOR_MOVER, seed); sleep(time); write(nextToTrucks[WRITE_END], &weight, sizeof(int)); printf("Mover %d brought down a box of weight %d in %d units of time\n", id, weight, time); } printf("Mover %d is done moving\n", id); free(args); return NULL; } // Routine for truckers void *trucker(void *arg) { Args *args = (Args *) arg; int id = args->id; unsigned int seed = args->seed; int capacity = ROOM_IN_TRUCK; int truckWeight = 0; int weight; printf("Hello from trucker %d\n", id); while (read(nextToTrucks[READ_END], &weight, sizeof(int)) > 0) { // Read from pipe, until movers are all done capacity--; truckWeight += weight; int time = RANDOM_WITHIN_RANGE(MIN_TIME_FOR_TRUCKER, MAX_TIME_FOR_TRUCKER, seed); sleep(time); printf("Trucker %d loaded up box of weight %d in %d units of time, room left: %d\n", id, weight, time, capacity); if (capacity == 0) { // If truck is full, go on trip, and reset time = RANDOM_WITHIN_RANGE(MIN_TRIP_TIME, MAX_TRIP_TIME, seed); printf("Full truck %d with load of %d units of mass departed. Round trip will take %d units of time\n", id, truckWeight, time); sleep(time); capacity = ROOM_IN_TRUCK; truckWeight = 0; } } // If truck is not full, go on trip, and end, as there are no more boxes int time = RANDOM_WITHIN_RANGE(MIN_TRIP_TIME, MAX_TRIP_TIME, seed); printf("Not full truck %d with load of %d units of mass departed. One way will take %d units of time\n", id, truckWeight, time); sleep(time); printf("Truck %d is finished\n", id); free(args); return NULL; } int main(int argc, char **argv) { srand(time(NULL)); pipe(houseFloor); pipe(nextToTrucks); // Get number of house dwellers, movers, and truckers int numberOfHouseDwellers, numberOfMovers, numberOfTruckers; printf("Please input number of people living in the house, number of movers and number of truck drivers\n"); scanf("%d %d %d", &numberOfHouseDwellers, &numberOfMovers, &numberOfTruckers); // Create thread pools, and pass in args pthread_t dwellerThreads[numberOfHouseDwellers]; pthread_t moverThreads[numberOfMovers]; pthread_t truckerThreads[numberOfTruckers]; for (int i = 0; i < numberOfHouseDwellers; i++) { Args *args = (Args *) malloc(sizeof(Args)); args->id = i; args->seed = rand(); pthread_create(&dwellerThreads[i], NULL, &dweller, (void *) args); } for (int i = 0; i < numberOfMovers; i++) { Args *args = (Args *) malloc(sizeof(Args)); args->id = i; args->seed = rand(); pthread_create(&moverThreads[i], NULL, &mover, (void *) args); } for (int i = 0; i < numberOfTruckers; i++) { Args *args = (Args *) malloc(sizeof(Args)); args->id = i; args->seed = rand(); pthread_create(&truckerThreads[i], NULL, &trucker, (void *) args); } // Wait for dwellers to finish and then close the house floor write, so movers know to stop for (int i = 0; i < numberOfHouseDwellers; i++) { pthread_join(dwellerThreads[i], NULL); } close(houseFloor[WRITE_END]); // Wait for movers to finish and then close the next to trucks write, so truckers know to stop // Also endings the read end of the house floor pipe, as no more boxes will be written to it for (int i = 0; i < numberOfMovers; i++) { pthread_join(moverThreads[i], NULL); } close(houseFloor[READ_END]); close(nextToTrucks[WRITE_END]); // Wait for truckers to finish, and close the read end of the next to trucks pipe, as no more boxes will be written to it for (int i = 0; i < numberOfTruckers; i++) { pthread_join(truckerThreads[i], NULL); } close(nextToTrucks[READ_END]); printf("Moving is finished!\n"); return EXIT_SUCCESS; }