1 // Copyright (C) 2012 Vicente Botet 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #define BOOST_THREAD_VERSION 4 7 8 #include <boost/thread/mutex.hpp> 9 #include <boost/thread/lockable_adapter.hpp> 10 #include <boost/thread/externally_locked.hpp> 11 #include <boost/thread/strict_lock.hpp> 12 #include <boost/thread/lock_types.hpp> 13 #include <iostream> 14 15 #ifdef BOOST_MSVC 16 # pragma warning(disable: 4355) // 'this' : used in base member initializer list 17 #endif 18 19 using namespace boost; 20 21 class BankAccount 22 { 23 int balance_; 24 public: Deposit(int amount)25 void Deposit(int amount) 26 { 27 balance_ += amount; 28 } Withdraw(int amount)29 void Withdraw(int amount) 30 { 31 balance_ -= amount; 32 } GetBalance()33 int GetBalance() 34 { 35 return balance_; 36 } 37 }; 38 39 //[AccountManager 40 class AccountManager: public basic_lockable_adapter<mutex> 41 { 42 public: 43 typedef basic_lockable_adapter<mutex> lockable_base_type; AccountManager()44 AccountManager() : 45 lockable_base_type(), checkingAcct_(*this), savingsAcct_(*this) 46 { 47 } 48 inline void Checking2Savings(int amount); 49 inline void AMoreComplicatedChecking2Savings(int amount); 50 private: 51 /*<-*/ some_condition()52 bool some_condition() 53 { 54 return true; 55 } /*->*/ 56 externally_locked<BankAccount, AccountManager > checkingAcct_; 57 externally_locked<BankAccount, AccountManager > savingsAcct_; 58 }; 59 //] 60 61 //[Checking2Savings Checking2Savings(int amount)62void AccountManager::Checking2Savings(int amount) 63 { 64 strict_lock<AccountManager> guard(*this); 65 checkingAcct_.get(guard).Withdraw(amount); 66 savingsAcct_.get(guard).Deposit(amount); 67 } 68 //] 69 70 //#if DO_NOT_COMPILE 71 ////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE 72 //void AccountManager::AMoreComplicatedChecking2Savings(int amount) { 73 // unique_lock<AccountManager> guard(*this); 74 // if (some_condition()) { 75 // guard.lock(); 76 // } 77 // checkingAcct_.get(guard).Withdraw(amount); 78 // savingsAcct_.get(guard).Deposit(amount); 79 // guard1.unlock(); 80 //} 81 ////] 82 //#elif DO_NOT_COMPILE_2 83 ////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2 84 //void AccountManager::AMoreComplicatedChecking2Savings(int amount) { 85 // unique_lock<AccountManager> guard1(*this); 86 // if (some_condition()) { 87 // guard1.lock(); 88 // } 89 // { 90 // strict_lock<AccountManager> guard(guard1); 91 // checkingAcct_.get(guard).Withdraw(amount); 92 // savingsAcct_.get(guard).Deposit(amount); 93 // } 94 // guard1.unlock(); 95 //} 96 ////] 97 //#else 98 ////[AMoreComplicatedChecking2Savings AMoreComplicatedChecking2Savings(int amount)99void AccountManager::AMoreComplicatedChecking2Savings(int amount) { 100 unique_lock<AccountManager> guard1(*this); 101 if (some_condition()) { 102 guard1.lock(); 103 } 104 { 105 nested_strict_lock<unique_lock<AccountManager> > guard(guard1); 106 checkingAcct_.get(guard).Withdraw(amount); 107 savingsAcct_.get(guard).Deposit(amount); 108 } 109 guard1.unlock(); 110 } 111 ////] 112 //#endif 113 main()114int main() 115 { 116 AccountManager mgr; 117 mgr.Checking2Savings(100); 118 return 0; 119 } 120 121