CSC-4730 / P6 / MutexSpit.cpp
MutexSpit.cpp
Raw
// CSC_4730 | P6 | Methods | Caleb Collar & Kai Kuebler | 10.29.21
#include "MutexSpit.hpp"

// Default constructor, create, fill, & shuffle the deck.
template <typename T>
Spit<T>::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 <typename T> Spit<T>::Spit(vector<T> &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 <typename T> void Spit<T>::action(vector<T> subDeck, uint32_t tid) {
  uint64_t workerSpit = 0;
  while (subDeck.size() > workerSpit) {
    for (auto i : subDeck) {
      if (i == pile) {
        lock_guard<mutex> 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 <typename T> void Spit<T>::PlayGame() {
  players.resize(numPlayers);
  for (uint32_t i = 0; i < numPlayers; i++) {
    vector<T> subDeck =
        i != numPlayers - 1
            ? vector<T>{deck.begin() + (i * (deck.size() / numPlayers)),
                        deck.begin() + (i + 1) * (deck.size() / numPlayers)}
            : vector<T>{deck.begin() + (i * (deck.size() / numPlayers)),
                        deck.end()};

    players.at(i) = thread(&Spit<T>::action, this, subDeck, i);
  }
}

// Destructor, if there are players in the game - will join them with the other
// threads.
template <typename T> Spit<T>::~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();
  }
}