// CSC_4730 | P6 | Methods | Caleb Collar & Kai Kuebler | 10.29.21 #include "MutexSpit.hpp" // Default constructor, create, fill, & shuffle the deck. template Spit::Spit(uint64_t sz, uint64_t seed, uint32_t nthreads) { size = sz; numPlayers = nthreads; deck.resize(size); //Fill the deck. for (uint32_t i = 0; i < size; i++) { deck.at(i) = i; } shuffle(deck.begin(), deck.end(), default_random_engine(seed)); //Shuffle the 'deck'. } // Overloaded constructor, take in predefined deck. template Spit::Spit(vector &deck, uint32_t nthreads) { size = deck.size(); numPlayers = nthreads; this->deck = deck; } // Player's worker 'action' compares items in subDeck 'hand' to item in critical // section. Will place item 'on' the pile by creating a lock. Will join other // threads when the 'hand' is empty. template void Spit::action(vector subDeck, uint32_t tid) { uint64_t workerSpit = 0; while (subDeck.size() > workerSpit) { for (auto i : subDeck) { if (i == pile) { lock_guard lock(m); workerSpit++; cout << "Thread:" << setw(5) << right << tid << " " << "hit on:" << setw(10) << right << pile << endl; pile++; } } } } // Method to start the players and the 'game'. template void Spit::PlayGame() { players.resize(numPlayers); for (uint32_t i = 0; i < numPlayers; i++) { vector subDeck = i != numPlayers - 1 ? vector{deck.begin() + (i * (deck.size() / numPlayers)), deck.begin() + (i + 1) * (deck.size() / numPlayers)} : vector{deck.begin() + (i * (deck.size() / numPlayers)), deck.end()}; players.at(i) = thread(&Spit::action, this, subDeck, i); } } // Destructor, if there are players in the game - will join them with the other // threads. template Spit::~Spit() { if (players.size() > 0) { // Here so that join isn't called when the user has instantiated spit - for (auto &it : players) //class, but didn't call PlayGame() before object ran out of scope. it.join(); } }