#include #include #include #include #include #include #define THINKING 0 /*philosopher is thinking*/ #define HUNGRY 1 /*philosopher is trying to get forks*/ #define EATING 2 /*philosopher is eating*/ typedef struct PhilosopherData { int eatingCount; int position; int state; pthread_t thread; } PhilosopherData; sem_t semaphore; bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers); void PhilosopherWait(); void Eat(PhilosopherData* philosopherSelected); int GetPhilosopherCount(char* argv); void* Philosopher(void* philosopherPassed); void PhilosopherInit(int philosopherTotal); void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal); void PutForks(PhilosopherData* philosopherSelected); void TakeForks(PhilosopherData* philosopherSelected); bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal); void Think(PhilosopherData* philosopherSelected); void AllowPhilosopher(); int main(int argc, char* argv[]) { if (argc < 2) printf("Too few arguments, exiting...\n"); if (argc > 2) printf("Too many arguments, exiting...\n"); if (argc == 2) { int philosopherTotal; philosopherTotal = GetPhilosopherCount(argv[1]); PhilosopherInit(philosopherTotal); } return 0; } // Takes in array of times each philosopher has eaten // If all philosophers have ate twice, then returns true // Otherwise, if a philosopher has not eaten twice, returns false bool AllPhilosophersFull(PhilosopherData PhilosopherList[], int numPhilosophers) { for (int i = 0; i < numPhilosophers; i++) if (PhilosopherList[i].eatingCount < 2) return false; return true; } // Philosopher enters critical section. void PhilosopherWait() { sem_wait(&semaphore); } // Sets philosopher to eating state and increments eating count. void Eat(PhilosopherData* philosopherSelected) { printf("Philosopher %d is eating...\n", philosopherSelected->position); philosopherSelected->state = EATING; ++philosopherSelected->eatingCount; } // Converts char* to number. int GetPhilosopherCount(char* argv) { int philosopherTotal; sscanf(argv, "%d", &philosopherTotal); return philosopherTotal; } // Main function that each thread runs. void* Philosopher(void* philosopherPassed) { PhilosopherData *philosopherSelected = (PhilosopherData*) philosopherPassed; while (true) { Think(philosopherSelected); /*philosopher is thinking*/ if (philosopherSelected->eatingCount == 2) { printf("Philosopher %d ate twice...\n", philosopherSelected->position); return; } TakeForks(philosopherSelected); /*acquire two forks or block*/ Eat(philosopherSelected); /*yum-yum, spaghetti*/ PutForks(philosopherSelected); /*put both forks back on table*/ } } // Handles all philosopher threads, finishes when all philosophers are full. void PhilosopherInit(int philosopherTotal) { PhilosopherData PhilosopherList[philosopherTotal]; PhilosopherListInit(PhilosopherList, philosopherTotal); sem_init(&semaphore, 0, 1); while (!AllPhilosophersFull(PhilosopherList, philosopherTotal)) { AllowPhilosopher(); sleep(1); } for (int i = 0; i < philosopherTotal; i++) { printf("Philosopher %d eating count: %d\n", PhilosopherList[i].position, PhilosopherList[i].eatingCount); } } // Initializes full list of philosophers. void PhilosopherListInit(PhilosopherData PhilosopherList[], int philosopherTotal) { for (int i = 0; i < philosopherTotal; i++) { PhilosopherList[i].position = i; PhilosopherList[i].eatingCount = 0; PhilosopherList[i].state = THINKING; pthread_create(&PhilosopherList[i].thread, NULL, &Philosopher, &PhilosopherList[i]); } } // Philosopher puts forks down. void PutForks(PhilosopherData* philosopherSelected) { printf("Philosopher %d is putting forks down...\n", philosopherSelected->position); } // Philosopher takes the forks on the left and right. void TakeForks(PhilosopherData* philosopherSelected) { philosopherSelected->state = HUNGRY; printf("Philosopher %d is hungry...\n", philosopherSelected->position); PhilosopherWait(); } // If philosopher is hungry and forks are free, then returns true. // Else, philosopher returns false. // Left philosopher math: (i+N-1)%N Right philosopher math: (i+1)%N bool PhilosopherCanEat(PhilosopherData PhilosopherList[], int selectedPosition, int philosopherTotal) { if (PhilosopherList[selectedPosition].state != HUNGRY) return false; for (int i = 0; i < philosopherTotal; i++) if (PhilosopherList[i].state == EATING) return false; return true; } // Philosopher begins thinking void Think(PhilosopherData* philosopherSelected) { printf("Philosopher %d is thinking...\n", philosopherSelected->position); philosopherSelected->state = THINKING; } // Philosopher exits critical section void AllowPhilosopher() { sem_post(&semaphore); }