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
19using namespace boost;
20
21class BankAccount
22{
23 int balance_;
24public:
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
40class AccountManager: public basic_lockable_adapter<mutex>
41{
42public:
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);
50private:
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
62void 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
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(lk&: guard).Withdraw(amount);
107 savingsAcct_.get(lk&: guard).Deposit(amount);
108 }
109 guard1.unlock();
110}
111////]
112//#endif
113
114int main()
115{
116 AccountManager mgr;
117 mgr.Checking2Savings(amount: 100);
118 return 0;
119}
120
121

source code of boost/libs/thread/example/ba_externallly_locked.cpp