libstdc++
unique_lock.h
Go to the documentation of this file.
1 // std::unique_lock implementation -*- C++ -*-
2 
3 // Copyright (C) 2008-2019 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/unique_lock.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{mutex}
28  */
29 
30 #ifndef _GLIBCXX_UNIQUE_LOCK_H
31 #define _GLIBCXX_UNIQUE_LOCK_H 1
32 
33 #pragma GCC system_header
34 
35 #if __cplusplus < 201103L
36 # include <bits/c++0x_warning.h>
37 #else
38 
39 #include <chrono>
40 #include <bits/move.h> // for std::swap
41 
42 namespace std _GLIBCXX_VISIBILITY(default)
43 {
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45 
46  /**
47  * @ingroup mutexes
48  * @{
49  */
50 
51  /** @brief A movable scoped lock type.
52  *
53  * A unique_lock controls mutex ownership within a scope. Ownership of the
54  * mutex can be delayed until after construction and can be transferred
55  * to another unique_lock by move construction or move assignment. If a
56  * mutex lock is owned when the destructor runs ownership will be released.
57  */
58  template<typename _Mutex>
60  {
61  public:
62  typedef _Mutex mutex_type;
63 
64  unique_lock() noexcept
65  : _M_device(0), _M_owns(false)
66  { }
67 
68  explicit unique_lock(mutex_type& __m)
69  : _M_device(std::__addressof(__m)), _M_owns(false)
70  {
71  lock();
72  _M_owns = true;
73  }
74 
75  unique_lock(mutex_type& __m, defer_lock_t) noexcept
76  : _M_device(std::__addressof(__m)), _M_owns(false)
77  { }
78 
79  unique_lock(mutex_type& __m, try_to_lock_t)
80  : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
81  { }
82 
83  unique_lock(mutex_type& __m, adopt_lock_t) noexcept
84  : _M_device(std::__addressof(__m)), _M_owns(true)
85  {
86  // XXX calling thread owns mutex
87  }
88 
89  template<typename _Clock, typename _Duration>
90  unique_lock(mutex_type& __m,
92  : _M_device(std::__addressof(__m)),
93  _M_owns(_M_device->try_lock_until(__atime))
94  { }
95 
96  template<typename _Rep, typename _Period>
97  unique_lock(mutex_type& __m,
98  const chrono::duration<_Rep, _Period>& __rtime)
99  : _M_device(std::__addressof(__m)),
100  _M_owns(_M_device->try_lock_for(__rtime))
101  { }
102 
103  ~unique_lock()
104  {
105  if (_M_owns)
106  unlock();
107  }
108 
109  unique_lock(const unique_lock&) = delete;
110  unique_lock& operator=(const unique_lock&) = delete;
111 
112  unique_lock(unique_lock&& __u) noexcept
113  : _M_device(__u._M_device), _M_owns(__u._M_owns)
114  {
115  __u._M_device = 0;
116  __u._M_owns = false;
117  }
118 
119  unique_lock& operator=(unique_lock&& __u) noexcept
120  {
121  if(_M_owns)
122  unlock();
123 
124  unique_lock(std::move(__u)).swap(*this);
125 
126  __u._M_device = 0;
127  __u._M_owns = false;
128 
129  return *this;
130  }
131 
132  void
133  lock()
134  {
135  if (!_M_device)
136  __throw_system_error(int(errc::operation_not_permitted));
137  else if (_M_owns)
138  __throw_system_error(int(errc::resource_deadlock_would_occur));
139  else
140  {
141  _M_device->lock();
142  _M_owns = true;
143  }
144  }
145 
146  bool
147  try_lock()
148  {
149  if (!_M_device)
150  __throw_system_error(int(errc::operation_not_permitted));
151  else if (_M_owns)
152  __throw_system_error(int(errc::resource_deadlock_would_occur));
153  else
154  {
155  _M_owns = _M_device->try_lock();
156  return _M_owns;
157  }
158  }
159 
160  template<typename _Clock, typename _Duration>
161  bool
162  try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
163  {
164  if (!_M_device)
165  __throw_system_error(int(errc::operation_not_permitted));
166  else if (_M_owns)
167  __throw_system_error(int(errc::resource_deadlock_would_occur));
168  else
169  {
170  _M_owns = _M_device->try_lock_until(__atime);
171  return _M_owns;
172  }
173  }
174 
175  template<typename _Rep, typename _Period>
176  bool
177  try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
178  {
179  if (!_M_device)
180  __throw_system_error(int(errc::operation_not_permitted));
181  else if (_M_owns)
182  __throw_system_error(int(errc::resource_deadlock_would_occur));
183  else
184  {
185  _M_owns = _M_device->try_lock_for(__rtime);
186  return _M_owns;
187  }
188  }
189 
190  void
191  unlock()
192  {
193  if (!_M_owns)
194  __throw_system_error(int(errc::operation_not_permitted));
195  else if (_M_device)
196  {
197  _M_device->unlock();
198  _M_owns = false;
199  }
200  }
201 
202  void
203  swap(unique_lock& __u) noexcept
204  {
205  std::swap(_M_device, __u._M_device);
206  std::swap(_M_owns, __u._M_owns);
207  }
208 
209  mutex_type*
210  release() noexcept
211  {
212  mutex_type* __ret = _M_device;
213  _M_device = 0;
214  _M_owns = false;
215  return __ret;
216  }
217 
218  bool
219  owns_lock() const noexcept
220  { return _M_owns; }
221 
222  explicit operator bool() const noexcept
223  { return owns_lock(); }
224 
225  mutex_type*
226  mutex() const noexcept
227  { return _M_device; }
228 
229  private:
230  mutex_type* _M_device;
231  bool _M_owns;
232  };
233 
234  /// Swap overload for unique_lock objects.
235  template<typename _Mutex>
236  inline void
237  swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
238  { __x.swap(__y); }
239 
240  // @} group mutexes
241 _GLIBCXX_END_NAMESPACE_VERSION
242 } // namespace
243 
244 #endif // C++11
245 #endif // _GLIBCXX_UNIQUE_LOCK_H
ISO C++ entities toplevel namespace is std.
Try to acquire ownership of the mutex without blocking.
Definition: std_mutex.h:132
duration
Definition: chrono:62
Do not acquire ownership of the mutex.
Definition: std_mutex.h:129
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:47
The standard mutex type.
Definition: std_mutex.h:83
A movable scoped lock type.
Definition: unique_lock.h:59
Assume the calling thread has already obtained mutex ownership and manage it.
Definition: std_mutex.h:136