CSC-4730 / P7 / FleegmanDillema.cpp
FleegmanDillema.cpp
Raw
//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;
}