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