1//
2// detail/scoped_lock.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef ASIO_DETAIL_SCOPED_LOCK_HPP
12#define ASIO_DETAIL_SCOPED_LOCK_HPP
13
14
15#include "asio/detail/noncopyable.hpp"
16
17#include "asio/detail/push_options.hpp"
18
19namespace asio {
20namespace detail {
21
22// Helper class to lock and unlock a mutex automatically.
23template <typename Mutex>
24class scoped_lock
25  : private noncopyable
26{
27public:
28  // Tag type used to distinguish constructors.
29  enum adopt_lock_t { adopt_lock };
30
31  // Constructor adopts a lock that is already held.
32  scoped_lock(Mutex& m, adopt_lock_t)
33    : mutex_(m),
34      locked_(true)
35  {
36  }
37
38  // Constructor acquires the lock.
39  explicit scoped_lock(Mutex& m)
40    : mutex_(m)
41  {
42    mutex_.lock();
43    locked_ = true;
44  }
45
46  // Destructor releases the lock.
47  ~scoped_lock()
48  {
49    if (locked_)
50      mutex_.unlock();
51  }
52
53  // Explicitly acquire the lock.
54  void lock()
55  {
56    if (!locked_)
57    {
58      mutex_.lock();
59      locked_ = true;
60    }
61  }
62
63  // Explicitly release the lock.
64  void unlock()
65  {
66    if (locked_)
67    {
68      mutex_.unlock();
69      locked_ = false;
70    }
71  }
72
73  // Test whether the lock is held.
74  bool locked() const
75  {
76    return locked_;
77  }
78
79  // Get the underlying mutex.
80  Mutex& mutex()
81  {
82    return mutex_;
83  }
84
85private:
86  // The underlying mutex.
87  Mutex& mutex_;
88
89  // Whether the mutex is currently locked or unlocked.
90  bool locked_;
91};
92
93} // namespace detail
94} // namespace asio
95
96#include "asio/detail/pop_options.hpp"
97
98#endif // ASIO_DETAIL_SCOPED_LOCK_HPP
99