Last active
October 6, 2015 11:19
-
-
Save valbok/5914bf0ed68a5e02f144 to your computer and use it in GitHub Desktop.
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
#include <mutex> | |
#include <thread> | |
#include <iostream> | |
#include <cassert> | |
#include <condition_variable> | |
using namespace std; | |
typedef float TCurrency; | |
const TCurrency empty = 0; | |
class Account { | |
public: | |
Account(TCurrency amount): mValue(amount), mReady(true) {} | |
Account(): Account(empty) {} | |
virtual bool transfer(Account& to, TCurrency amount) { | |
unique_lock<mutex> lock1(mMutex, defer_lock); | |
unique_lock<mutex> lock2(to.mMutex, defer_lock); | |
lock(lock1, lock2); | |
mReady = false; | |
to.mReady = false; | |
this_thread::sleep_for(chrono::seconds(1)); | |
bool result = false; | |
if (amount >= mValue) { | |
to.mValue += amount; | |
mValue -= amount; | |
result = true; | |
} | |
mReady = true; | |
to.mReady = true; | |
return result; | |
} | |
virtual TCurrency value() const { | |
unique_lock<mutex> lock(mMutex); | |
condition_variable cv; | |
cv.wait(lock, [this]{return mReady;}); | |
return mValue; | |
} | |
private: | |
TCurrency mValue; | |
mutable mutex mMutex; | |
bool mReady; | |
}; | |
void transfer(Account &from, Account &to, TCurrency amount) { | |
auto v_to = to.value(); | |
auto v_from = from.value(); | |
if (from.transfer(to, amount)) { | |
auto now_from = from.value(); | |
assert((v_from - amount) == now_from); | |
auto now_to = to.value(); | |
assert((v_to + amount) == now_to); | |
} | |
} | |
int main() { | |
Account a(5), b(1), c(10), d(15); | |
thread t1(transfer, ref(a), ref(b), 3); | |
thread t2(transfer, ref(a), ref(c), 2); | |
thread t3(transfer, ref(b), ref(c), 1); | |
thread t4(transfer, ref(c), ref(a), 5.5); | |
thread t5(transfer, ref(d), ref(a), 2); | |
thread t6(transfer, ref(d), ref(b), 3); | |
thread t7(transfer, ref(c), ref(b), 4); | |
thread t8(transfer, ref(a), ref(b), 2); | |
t1.join(); | |
t2.join(); | |
t3.join(); | |
t4.join(); | |
t5.join(); | |
t6.join(); | |
t7.join(); | |
t8.join(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment