libstdc++
unique_lock.h
Go to the documentation of this file.
1// std::unique_lock implementation -*- C++ -*-
2
3// Copyright (C) 2008-2023 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 <bits/chrono.h>
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 * @headerfile mutex
55 * @ingroup mutexes
56 * @since C++11
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,
99 : _M_device(std::__addressof(__m)),
100 _M_owns(_M_device->try_lock_for(__rtime))
101 { }
102
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 _GLIBCXX_NODISCARD
147 bool
148 try_lock()
149 {
150 if (!_M_device)
151 __throw_system_error(int(errc::operation_not_permitted));
152 else if (_M_owns)
153 __throw_system_error(int(errc::resource_deadlock_would_occur));
154 else
155 {
156 _M_owns = _M_device->try_lock();
157 return _M_owns;
158 }
159 }
160
161 template<typename _Clock, typename _Duration>
162 _GLIBCXX_NODISCARD
163 bool
164 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
165 {
166 if (!_M_device)
167 __throw_system_error(int(errc::operation_not_permitted));
168 else if (_M_owns)
169 __throw_system_error(int(errc::resource_deadlock_would_occur));
170 else
171 {
172 _M_owns = _M_device->try_lock_until(__atime);
173 return _M_owns;
174 }
175 }
176
177 template<typename _Rep, typename _Period>
178 _GLIBCXX_NODISCARD
179 bool
180 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
181 {
182 if (!_M_device)
183 __throw_system_error(int(errc::operation_not_permitted));
184 else if (_M_owns)
185 __throw_system_error(int(errc::resource_deadlock_would_occur));
186 else
187 {
188 _M_owns = _M_device->try_lock_for(__rtime);
189 return _M_owns;
190 }
191 }
192
193 void
194 unlock()
195 {
196 if (!_M_owns)
197 __throw_system_error(int(errc::operation_not_permitted));
198 else if (_M_device)
199 {
200 _M_device->unlock();
201 _M_owns = false;
202 }
203 }
204
205 void
206 swap(unique_lock& __u) noexcept
207 {
208 std::swap(_M_device, __u._M_device);
209 std::swap(_M_owns, __u._M_owns);
210 }
211
212 mutex_type*
213 release() noexcept
214 {
215 mutex_type* __ret = _M_device;
216 _M_device = 0;
217 _M_owns = false;
218 return __ret;
219 }
220
221 _GLIBCXX_NODISCARD
222 bool
223 owns_lock() const noexcept
224 { return _M_owns; }
225
226 explicit operator bool() const noexcept
227 { return owns_lock(); }
228
229 _GLIBCXX_NODISCARD
230 mutex_type*
231 mutex() const noexcept
232 { return _M_device; }
233
234 private:
235 mutex_type* _M_device;
236 bool _M_owns;
237 };
238
239 /// Swap overload for unique_lock objects.
240 /// @relates unique_lock
241 template<typename _Mutex>
242 inline void
244 { __x.swap(__y); }
245
246_GLIBCXX_END_NAMESPACE_VERSION
247} // namespace
248
249#endif // C++11
250#endif // _GLIBCXX_UNIQUE_LOCK_H
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
ISO C++ entities toplevel namespace is std.
chrono::duration represents a distance between two points in time
Definition: chrono.h:524
chrono::time_point represents a point in time as measured by a clock
Definition: chrono.h:934
Do not acquire ownership of the mutex.
Definition: std_mutex.h:216
Try to acquire ownership of the mutex without blocking.
Definition: std_mutex.h:219
Assume the calling thread has already obtained mutex ownership and manage it.
Definition: std_mutex.h:223
A movable scoped lock type.
Definition: unique_lock.h:60
void swap(unique_lock< _Mutex > &__x, unique_lock< _Mutex > &__y) noexcept
Swap overload for unique_lock objects.
Definition: unique_lock.h:243