#include std::mutex changingForkState; std::mutex printing; void Philosopher::setState(PhilosopherState state) { this->state = state; } size_t Philosopher::leftPhilosopherNumber(void) { // Circular implementation of the table to the left. // (0 - 1 + 9) % 9 = 8 // (1 - 1 + 9) % 9 = 0 return (numberOfPhilosopher - 1 + philosophers->size()) % philosophers->size(); } size_t Philosopher::rightPhilosopherNumber(void) { // Circular implementation of the table to the right. // (8 + 1) % 9 = 0 // (7 + 1) % 9 = 8 return (numberOfPhilosopher + 1) % philosophers->size(); } PhilosopherPtr Philosopher::leftPhilosopher(void) { return (*philosophers)[leftPhilosopherNumber()]; } PhilosopherPtr Philosopher::rightPhilosopher(void) { return (*philosophers)[rightPhilosopherNumber()]; } void Philosopher::think() { // The number of milliseconds thinking. size_t duration = random(100, 1000); { // Holds the lock for printing. std::lock_guard lk{printing}; std::cout << "Philosopher " << numberOfPhilosopher << " is thinking for " << duration << "." << std::endl; } // Sleeps. std::this_thread::sleep_for(std::chrono::milliseconds(duration)); } void Philosopher::takeForks() { { // Holds the lock for state manipulation and read. std::lock_guard lk{changingForkState}; // Sets the philosopher to be hungry. setState(PhilosopherState::HUNGRY); { // Holds the lock for printing. std::lock_guard lk{printing}; std::cout << "Philosopher " << numberOfPhilosopher << " is hungry." << std::endl; } // Attempts to release the binary semaphore for forks locking if still up. test(); } // Attempts to adquire the forks lock. hasBothForks.acquire(); } void Philosopher::eat() { // Sets the time eating. size_t duration = random(100, 1000); { // Holds the lock for printing. std::lock_guard lk{printing}; std::cout << "Philosopher " << numberOfPhilosopher << " is eating." << std::endl; } // Sleeps the time the philosopher last to eat. std::this_thread::sleep_for(std::chrono::milliseconds(duration)); } void Philosopher::putForks() { // Holds the lock for state manipulation and read. std::lock_guard lk{changingForkState}; // Set the philosopher in thinking state. setState(PhilosopherState::THINKING); // Attempts to free the lock of neighbors if they are locked because of this philosopher. leftPhilosopher()->test(); rightPhilosopher()->test(); } PhilosopherState Philosopher::getState() { return state; } Philosopher::Philosopher(ListOfPhilosophersPtr philosophers, int numberOfPhilosopher): state(PhilosopherState::THINKING) { this->numberOfPhilosopher = numberOfPhilosopher; this->philosophers = philosophers; } void Philosopher::startThread() { { std::lock_guard lk{printing}; std::cout << "Philosopher " << numberOfPhilosopher << " has sit in the table." << std::endl; } while (true) { // The philosopher starts thinking. think(); // Then gets hungry and attempts to eat. takeForks(); // When the two forks are available the philosopher eats. eat(); // Then the philosopher puts the two forks on the table to be used by the philosopher's neighbors. putForks(); } } void Philosopher::test() { // This is self-documenting. if (state == PhilosopherState::HUNGRY && leftPhilosopher()->getState() != PhilosopherState::EATING && rightPhilosopher()->getState() != PhilosopherState::EATING) { setState(PhilosopherState::EATING); hasBothForks.release(); } }