1// std::unique_lock implementation -*- C++ -*- 
2 
3// Copyright (C) 2008-2021 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#include <bits/std_mutex.h> // for std::defer_lock_t 
42 
43namespace std _GLIBCXX_VISIBILITY(default
44
45_GLIBCXX_BEGIN_NAMESPACE_VERSION 
46 
47 /** @brief A movable scoped lock type. 
48 * 
49 * A unique_lock controls mutex ownership within a scope. Ownership of the 
50 * mutex can be delayed until after construction and can be transferred 
51 * to another unique_lock by move construction or move assignment. If a 
52 * mutex lock is owned when the destructor runs ownership will be released. 
53 * 
54 * @ingroup mutexes 
55 */ 
56 template<typename _Mutex> 
57 class unique_lock 
58
59 public
60 typedef _Mutex mutex_type
61 
62 unique_lock() noexcept 
63 : _M_device(0), _M_owns(false
64 { } 
65 
66 explicit unique_lock(mutex_type& __m
67 : _M_device(std::__addressof(__m)), _M_owns(false
68
69 lock(); 
70 _M_owns = true
71
72 
73 unique_lock(mutex_type& __m, defer_lock_t) noexcept 
74 : _M_device(std::__addressof(__m)), _M_owns(false
75 { } 
76 
77 unique_lock(mutex_type& __m, try_to_lock_t
78 : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) 
79 { } 
80 
81 unique_lock(mutex_type& __m, adopt_lock_t) noexcept 
82 : _M_device(std::__addressof(__m)), _M_owns(true
83
84 // XXX calling thread owns mutex 
85
86 
87 template<typename _Clock, typename _Duration> 
88 unique_lock(mutex_type& __m
89 const chrono::time_point<_Clock, _Duration>& __atime
90 : _M_device(std::__addressof(__m)), 
91 _M_owns(_M_device->try_lock_until(__atime)) 
92 { } 
93 
94 template<typename _Rep, typename _Period> 
95 unique_lock(mutex_type& __m
96 const chrono::duration<_Rep, _Period>& __rtime
97 : _M_device(std::__addressof(__m)), 
98 _M_owns(_M_device->try_lock_for(__rtime)) 
99 { } 
100 
101 ~unique_lock() 
102
103 if (_M_owns
104 unlock(); 
105
106 
107 unique_lock(const unique_lock&) = delete
108 unique_lock& operator=(const unique_lock&) = delete
109 
110 unique_lock(unique_lock&& __u) noexcept 
111 : _M_device(__u._M_device), _M_owns(__u._M_owns) 
112
113 __u._M_device = 0
114 __u._M_owns = false
115
116 
117 unique_lock& operator=(unique_lock&& __u) noexcept 
118
119 if(_M_owns
120 unlock(); 
121 
122 unique_lock(std::move(__u)).swap(*this); 
123 
124 __u._M_device = 0
125 __u._M_owns = false
126 
127 return *this
128
129 
130 void 
131 lock() 
132
133 if (!_M_device
134 __throw_system_error(int(errc::operation_not_permitted)); 
135 else if (_M_owns
136 __throw_system_error(int(errc::resource_deadlock_would_occur)); 
137 else 
138
139 _M_device->lock(); 
140 _M_owns = true
141
142
143 
144 bool 
145 try_lock() 
146
147 if (!_M_device
148 __throw_system_error(int(errc::operation_not_permitted)); 
149 else if (_M_owns
150 __throw_system_error(int(errc::resource_deadlock_would_occur)); 
151 else 
152
153 _M_owns = _M_device->try_lock(); 
154 return _M_owns
155
156
157 
158 template<typename _Clock, typename _Duration> 
159 bool 
160 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime
161
162 if (!_M_device
163 __throw_system_error(int(errc::operation_not_permitted)); 
164 else if (_M_owns
165 __throw_system_error(int(errc::resource_deadlock_would_occur)); 
166 else 
167
168 _M_owns = _M_device->try_lock_until(__atime); 
169 return _M_owns
170
171
172 
173 template<typename _Rep, typename _Period> 
174 bool 
175 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime
176
177 if (!_M_device
178 __throw_system_error(int(errc::operation_not_permitted)); 
179 else if (_M_owns
180 __throw_system_error(int(errc::resource_deadlock_would_occur)); 
181 else 
182
183 _M_owns = _M_device->try_lock_for(__rtime); 
184 return _M_owns
185
186
187 
188 void 
189 unlock() 
190
191 if (!_M_owns
192 __throw_system_error(int(errc::operation_not_permitted)); 
193 else if (_M_device
194
195 _M_device->unlock(); 
196 _M_owns = false
197
198
199 
200 void 
201 swap(unique_lock& __u) noexcept 
202
203 std::swap(_M_device, __u._M_device); 
204 std::swap(_M_owns, __u._M_owns); 
205
206 
207 mutex_type
208 release() noexcept 
209
210 mutex_type* __ret = _M_device
211 _M_device = 0
212 _M_owns = false
213 return __ret
214
215 
216 bool 
217 owns_lock() const noexcept 
218 { return _M_owns; } 
219 
220 explicit operator bool() const noexcept 
221 { return owns_lock(); } 
222 
223 mutex_type
224 mutex() const noexcept 
225 { return _M_device; } 
226 
227 private
228 mutex_type* _M_device
229 bool _M_owns
230 }; 
231 
232 /// Swap overload for unique_lock objects. 
233 /// @relates unique_lock 
234 template<typename _Mutex> 
235 inline void 
236 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept 
237 { __x.swap(__y); } 
238 
239_GLIBCXX_END_NAMESPACE_VERSION 
240} // namespace 
241 
242#endif // C++11 
243#endif // _GLIBCXX_UNIQUE_LOCK_H 
244