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