libstdc++
unique_lock.h
Go to the documentation of this file.
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
42namespace 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>
57 {
58 public:
59 typedef _Mutex mutex_type;
60
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
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
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,
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,
96 : _M_device(std::__addressof(__m)),
97 _M_owns(_M_device->try_lock_for(__rtime))
98 { }
99
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
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
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
236 { __x.swap(__y); }
237
238_GLIBCXX_END_NAMESPACE_VERSION
239} // namespace
240
241#endif // C++11
242#endif // _GLIBCXX_UNIQUE_LOCK_H
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:101
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:49
ISO C++ entities toplevel namespace is std.
The standard mutex type.
Definition std_mutex.h:84
Do not acquire ownership of the mutex.
Definition std_mutex.h:129
Try to acquire ownership of the mutex without blocking.
Definition std_mutex.h:132
Assume the calling thread has already obtained mutex ownership and manage it.
Definition std_mutex.h:136
A movable scoped lock type.
Definition unique_lock.h:57
void swap(unique_lock< _Mutex > &__x, unique_lock< _Mutex > &__y) noexcept
Swap overload for unique_lock objects.