Skip to content

Instantly share code, notes, and snippets.

@valbok
Last active October 6, 2015 11:19
Show Gist options
  • Save valbok/5914bf0ed68a5e02f144 to your computer and use it in GitHub Desktop.
Save valbok/5914bf0ed68a5e02f144 to your computer and use it in GitHub Desktop.
#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