summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/thread/example/ba_externallly_locked.cpp
blob: e93876769ee4fa18de175d785538319b662b8ab4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// 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 <boost/thread/mutex.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/externally_locked.hpp>
#include <boost/thread/strict_lock.hpp>
#include <boost/thread/lock_types.hpp>
#include <iostream>

#ifdef BOOST_MSVC
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
#endif

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: public basic_lockable_adapter<mutex>
{
public:
  typedef basic_lockable_adapter<mutex> lockable_base_type;
  AccountManager() :
    lockable_base_type(), checkingAcct_(*this), savingsAcct_(*this)
  {
  }
  inline void Checking2Savings(int amount);
  inline void AMoreComplicatedChecking2Savings(int amount);
private:
  /*<-*/
  bool some_condition()
  {
    return true;
  } /*->*/
  externally_locked<BankAccount, AccountManager > checkingAcct_;
  externally_locked<BankAccount, AccountManager > savingsAcct_;
};
//]

//[Checking2Savings
void AccountManager::Checking2Savings(int amount)
{
  strict_lock<AccountManager> guard(*this);
  checkingAcct_.get(guard).Withdraw(amount);
  savingsAcct_.get(guard).Deposit(amount);
}
//]

//#if DO_NOT_COMPILE
////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE
//void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
//    unique_lock<AccountManager> guard(*this);
//    if (some_condition()) {
//        guard.lock();
//    }
//    checkingAcct_.get(guard).Withdraw(amount);
//    savingsAcct_.get(guard).Deposit(amount);
//    guard1.unlock();
//}
////]
//#elif DO_NOT_COMPILE_2
////[AMoreComplicatedChecking2Savings_DO_NOT_COMPILE2
//void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
//    unique_lock<AccountManager> guard1(*this);
//    if (some_condition()) {
//        guard1.lock();
//    }
//    {
//        strict_lock<AccountManager> guard(guard1);
//        checkingAcct_.get(guard).Withdraw(amount);
//        savingsAcct_.get(guard).Deposit(amount);
//    }
//    guard1.unlock();
//}
////]
//#else
////[AMoreComplicatedChecking2Savings
void AccountManager::AMoreComplicatedChecking2Savings(int amount) {
    unique_lock<AccountManager> guard1(*this);
    if (some_condition()) {
        guard1.lock();
    }
    {
        nested_strict_lock<unique_lock<AccountManager> > guard(guard1);
        checkingAcct_.get(guard).Withdraw(amount);
        savingsAcct_.get(guard).Deposit(amount);
    }
    guard1.unlock();
}
////]
//#endif

int main()
{
  AccountManager mgr;
  mgr.Checking2Savings(100);
  return 0;
}