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: |
25 | void Deposit(int amount) |
26 | { |
27 | balance_ += amount; |
28 | } |
29 | void Withdraw(int amount) |
30 | { |
31 | balance_ -= amount; |
32 | } |
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; |
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 | /*<-*/ |
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 |
62 | void AccountManager::Checking2Savings(int amount) |
63 | { |
64 | strict_lock<AccountManager> guard(*this); |
65 | checkingAcct_.get(lk&: guard).Withdraw(amount); |
66 | savingsAcct_.get(lk&: 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 |
99 | void 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(lk&: guard).Withdraw(amount); |
107 | savingsAcct_.get(lk&: guard).Deposit(amount); |
108 | } |
109 | guard1.unlock(); |
110 | } |
111 | ////] |
112 | //#endif |
113 | |
114 | int main() |
115 | { |
116 | AccountManager mgr; |
117 | mgr.Checking2Savings(amount: 100); |
118 | return 0; |
119 | } |
120 | |
121 |