Created
April 20, 2018 05:46
-
-
Save mkolod/b16a849b21a4b4f2fb8889a630a24703 to your computer and use it in GitHub Desktop.
C++11 Dining Philosophers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//----------------------------------------------------------------------------- | |
// Desc: Dining Philosophers sample. | |
// | |
// Demonstrates how to use Monitor object (lock) to protect critical section. | |
// | |
// Scenario is such that there are 5 philosophers and 5 tools on each side of a philosopher. | |
// Each philosopher can only take one tool on the left and one on the right. | |
// One of the philosophers must wait for a tool to become available because whoever grabs | |
// a tool will hold it until he eats and puts the tool back on the table. | |
// | |
// Application of the pattern could be transferring money from account A to account B. | |
// Important here is to pass locking objects always in the same (increasing) order. | |
// If the order is mixed you would encounter random deadlocks at runtime. | |
//----------------------------------------------------------------------------- | |
#include <algorithm> | |
#include <iostream> | |
#include <memory> | |
#include <mutex> | |
#include <string> | |
#include <thread> | |
#include <exception> | |
#include <vector> | |
#include <cstddef> | |
using namespace std; | |
class Chopstick | |
{ | |
public: | |
Chopstick(){}; | |
mutex m; | |
}; | |
int main() | |
{ | |
auto eat = [](Chopstick* leftChopstick, Chopstick* rightChopstick, int philosopherNumber, int leftChopstickNumber, int rightChopstickNumber) | |
{ | |
if (leftChopstick == rightChopstick) | |
{ | |
throw runtime_error("Left and right chopsticks should not be the same!"); | |
} | |
lock(leftChopstick->m, rightChopstick->m); // ensures there are no deadlocks | |
lock_guard<mutex> a(leftChopstick->m, adopt_lock); | |
string sl = " Philosopher " + to_string(philosopherNumber) + " picked " + to_string(leftChopstickNumber) + " chopstick.\n"; | |
cout << sl.c_str(); | |
lock_guard<mutex> b(rightChopstick->m, adopt_lock); | |
string sr = " Philosopher " + to_string(philosopherNumber) + " picked " + to_string(rightChopstickNumber) + " chopstick.\n"; | |
cout << sr.c_str(); | |
string pe = "Philosopher " + to_string(philosopherNumber) + " eats.\n"; | |
cout << pe; | |
}; | |
static const size_t numPhilosophers = 5; | |
vector< unique_ptr<Chopstick> > chopsticks(numPhilosophers); | |
for (size_t i {0}; i < numPhilosophers; ++i) | |
{ | |
auto c1 = unique_ptr<Chopstick>(new Chopstick()); //make_unique in C++14 | |
chopsticks[i] = move(c1); | |
} | |
// This is where we create philosophers, each of 5 tasks represents one philosopher. | |
vector<thread> tasks(numPhilosophers); | |
tasks[0] = thread(eat, | |
chopsticks[0].get(), // left chopstick: #1 | |
chopsticks[numPhilosophers - 1].get(), // right chopstick: #5 | |
0 + 1, // philosopher number | |
1, // left chopstick number | |
numPhilosophers // right chopstick number | |
); | |
for (size_t i{1}; i < numPhilosophers; ++i) | |
{ | |
tasks[i] = (thread(eat, | |
chopsticks[i - 1].get(), // left chopstick | |
chopsticks[i].get(), // right chopstick | |
i + 1, // philosopher number | |
i, // left chopstick number | |
i + 1 // right chopstick number | |
) | |
); | |
} | |
for_each(tasks.begin(), tasks.end(), mem_fn(&thread::join)); | |
return 0; | |
} | |
/* | |
Philosopher 1 picked 1 chopstick. | |
Philosopher 3 picked 2 chopstick. | |
Philosopher 1 picked 5 chopstick. | |
Philosopher 3 picked 3 chopstick. | |
Philosopher 1 eats. | |
Philosopher 3 eats. | |
Philosopher 5 picked 4 chopstick. | |
Philosopher 2 picked 1 chopstick. | |
Philosopher 2 picked 2 chopstick. | |
Philosopher 5 picked 5 chopstick. | |
Philosopher 2 eats. | |
Philosopher 5 eats. | |
Philosopher 4 picked 3 chopstick. | |
Philosopher 4 picked 4 chopstick. | |
Philosopher 4 eats. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment