//CSC_4730 | P7 | Fleegman's Dillema; With c++11 Mutexes & Threads| Caleb A. Collar | 11.8.21 #include <getopt.h> #include <stdint.h> #include <iostream> #include <mutex> #include <thread> using namespace std; //One byte, only 0b0 up to 0b101 is needed. typedef uint8_t n; //Number of Guy Fleegman's friends. const n numPlayers = 5; //Pointer to threads. thread* friends[numPlayers]; //The flugelhorns, which are mutually exclusive. mutex flugelhorns[numPlayers]; //Protect cout so that no output will overlay any other output. inline void ProtectCout(const string info){ static mutex coutMutex; coutMutex.lock(); cout << info << endl; coutMutex.unlock(); } //Spawns and then joins threads. inline void UseAlgorithm(void (*algorithm)(n)){ for (n i = 0; i < numPlayers; i++){ //Spawn player threads with specified algorithm. friends[i] = new thread(algorithm, i); } for (n i = 0; i < numPlayers; i++){ //Join threads when finished. friends[i]->join(); } } //Fleegman's algorithm (acquire lock n and then lock n + 1) that results in a deadlock. inline void FleegmanAlgorithm(n tid){ while (true){ //Thread wants to play. flugelhorns[tid].lock(); //Pick up first horn. flugelhorns[(tid + 1) % numPlayers].lock(); //Pick up second horn. ProtectCout("Player[" + to_string(tid) + "] is playing flugelhorns..."); //Play the horns for a bit. flugelhorns[(tid + 1) % numPlayers].unlock(); //Put down second horn. flugelhorns[tid].unlock(); //Put down first horn. sched_yield(); //Voluntarily yield the cpu. } } inline void TryLock(n tid){ while (true){ try_lock(flugelhorns[tid], flugelhorns[(tid + 1) % numPlayers]); ProtectCout("Player[" + to_string(tid) + "] is playing flugelhorns..."); //Play the horns for a bit. flugelhorns[(tid + 1) % numPlayers].unlock(); flugelhorns[tid].unlock(); sched_yield(); //Voluntarily yield the cpu. } } //Another lock based algorithm (last friend reaches other direction)that doesn't result in a deadlock. inline void MyAlgorithm(n tid){ while (true){ if (tid == numPlayers - 1){ //Modify the behavior of the last player. flugelhorns[(tid + 1) % numPlayers].lock(); //Pick up second horn first. flugelhorns[tid].lock(); //Then, pick up first horn. }else{ flugelhorns[tid].lock(); //Pick up first horn. flugelhorns[(tid + 1) % numPlayers].lock(); //Then, pick up second horn. } ProtectCout("Player[" + to_string(tid) + "] is playing flugelhorns..."); //Play the horns for a bit. flugelhorns[(tid + 1) % numPlayers].unlock(); //Put down second horn. flugelhorns[tid].unlock(); //Put down first horn. sched_yield(); //Voluntarily yield the cpu. } } //Main handles input args. int main(int argc, char *argv[]){ void (*algorithm)(n); int8_t c; while ((c = getopt(argc, argv, "gtoh"))){ switch (c){ case 'g': algorithm = FleegmanAlgorithm; goto run; case 't': algorithm = TryLock; goto run; case 'o': algorithm = MyAlgorithm; goto run; run: UseAlgorithm(algorithm); break; case 'h': default: cout <<"| Guy Fleegman's Dillema of His Favorite Flugelhorn Quintet |\n"; cout <<"-g For Guy Fleegman's algorithm.\n-o Other lock based algorithm.\n-t Uses try_lock.\n"; exit(0); } } return 0; }