// Copyright (C) 2012 Vicente Botet // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #define BOOST_THREAD_VERSION 4 #include #include #include #include #include using namespace boost; class BankAccount { int balance_; public: void Deposit(int amount) { balance_ += amount; } void Withdraw(int amount) { balance_ -= amount; } int GetBalance() { return balance_; } }; //[AccountManager class AccountManager { mutex mtx_; public: AccountManager() : checkingAcct_(mtx_), savingsAcct_(mtx_) { } inline void Checking2Savings(int amount); inline void AMoreComplicatedChecking2Savings(int amount); private: /*<-*/ bool some_condition() { return true; } /*->*/ externally_locked checkingAcct_; externally_locked savingsAcct_; }; //] //[Checking2Savings void AccountManager::Checking2Savings(int amount) { strict_lock guard(mtx_); checkingAcct_.get(guard).Withdraw(amount); savingsAcct_.get(guard).Deposit(amount); } //] #if MUST_NOT_COMPILE //[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE void AccountManager::AMoreComplicatedChecking2Savings(int amount) { unique_lock guard(mtx_); if (some_condition()) { guard.lock(); } checkingAcct_.get(guard).Withdraw(amount); savingsAcct_.get(guard).Deposit(amount); guard1.unlock(); } //] #elif MUST_NOT_COMPILE_2 //[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2 void AccountManager::AMoreComplicatedChecking2Savings(int amount) { unique_lock guard1(mtx_); if (some_condition()) { guard1.lock(); } { strict_lock guard(guard1); checkingAcct_.get(guard).Withdraw(amount); savingsAcct_.get(guard).Deposit(amount); } guard1.unlock(); } ] #else //[AMoreComplicatedChecking2Savings void AccountManager::AMoreComplicatedChecking2Savings(int amount) { unique_lock guard1(mtx_); if (some_condition()) { guard1.lock(); } { nested_strict_lock > guard(guard1); checkingAcct_.get(guard).Withdraw(amount); savingsAcct_.get(guard).Deposit(amount); } guard1.unlock(); } //] #endif int main() { AccountManager mgr; mgr.Checking2Savings(100); return 0; }