...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <mutex> #include <thread> class bank_account { int balance; public: std::mutex balance_mutex; bank_account() = delete; bank_account(int initial_amount) : balance(initial_amount) {} int get_balance() { return balance; } void set_balance(int amount) { balance = amount; } }; int deposit(bank_account *from, bank_account *to, int amount) { std::lock_guard<std::mutex> from_guardlock(from->balance_mutex); /* Not enough balance to transfer */ if (from->get_balance() < amount) { return -1; /* Indicate error */ } std::lock_guard<std::mutex> to_guardlock(to->balance_mutex); from->set_balance(from->get_balance() - amount); to->set_balance(to->get_balance() + amount); return 0; } int main(void) { bank_account *ba1 = new bank_account(1000); bank_account *ba2 = new bank_account(1000); /* Perform the deposits */ std::thread thr1(deposit, ba1, ba2, 100); std::thread thr2(deposit, ba2, ba1, 100); thr1.join(); thr2.join(); return 0; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <atomic> #include <mutex> #include <thread> class bank_account { static std::atomic<unsigned int> global_id; const unsigned int id; int balance; public: std::mutex balance_mutex; bank_account() = delete; bank_account(int initial_amount) : id(global_id++), balance(initial_amount) {} unsigned int get_id() { return id; } int get_balance() { return balance; } void set_balance(int amount) { balance = amount; } }; std::atomic<unsigned int> bank_account::global_id(1); int deposit(bank_account *from, bank_account *to, int amount) { int result = -1; std::mutex *first; std::mutex *second; if (from->get_id() == to->get_id()) { return -1; /* Indicate error */ } /* Ensure proper ordering for locking */ if (from->get_id() < to->get_id()) { first = &from->balance_mutex; second = &to->balance_mutex; } else { first = &to->balance_mutex; second = &from->balance_mutex; } std::lock_guard<std::mutex> first_guardlock(*first); std::lock_guard<std::mutex> second_guardlock(*second); /* Check for enough balance to transfer */ if (from->get_balance() >= amount) { from->set_balance(from->get_balance() - amount); to->set_balance(to->get_balance() + amount); result = 0; } return result; } |
...