1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP___CXX03_MUTEX 11#define _LIBCPP___CXX03_MUTEX 12 13/* 14 mutex synopsis 15 16namespace std 17{ 18 19class mutex 20{ 21public: 22 constexpr mutex() noexcept; 23 ~mutex(); 24 25 mutex(const mutex&) = delete; 26 mutex& operator=(const mutex&) = delete; 27 28 void lock(); 29 bool try_lock(); 30 void unlock(); 31 32 typedef pthread_mutex_t* native_handle_type; 33 native_handle_type native_handle(); 34}; 35 36class recursive_mutex 37{ 38public: 39 recursive_mutex(); 40 ~recursive_mutex(); 41 42 recursive_mutex(const recursive_mutex&) = delete; 43 recursive_mutex& operator=(const recursive_mutex&) = delete; 44 45 void lock(); 46 bool try_lock() noexcept; 47 void unlock(); 48 49 typedef pthread_mutex_t* native_handle_type; 50 native_handle_type native_handle(); 51}; 52 53class timed_mutex 54{ 55public: 56 timed_mutex(); 57 ~timed_mutex(); 58 59 timed_mutex(const timed_mutex&) = delete; 60 timed_mutex& operator=(const timed_mutex&) = delete; 61 62 void lock(); 63 bool try_lock(); 64 template <class Rep, class Period> 65 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 66 template <class Clock, class Duration> 67 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 68 void unlock(); 69}; 70 71class recursive_timed_mutex 72{ 73public: 74 recursive_timed_mutex(); 75 ~recursive_timed_mutex(); 76 77 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 78 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 79 80 void lock(); 81 bool try_lock() noexcept; 82 template <class Rep, class Period> 83 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 84 template <class Clock, class Duration> 85 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 86 void unlock(); 87}; 88 89struct defer_lock_t { explicit defer_lock_t() = default; }; 90struct try_to_lock_t { explicit try_to_lock_t() = default; }; 91struct adopt_lock_t { explicit adopt_lock_t() = default; }; 92 93inline constexpr defer_lock_t defer_lock{}; 94inline constexpr try_to_lock_t try_to_lock{}; 95inline constexpr adopt_lock_t adopt_lock{}; 96 97template <class Mutex> 98class lock_guard 99{ 100public: 101 typedef Mutex mutex_type; 102 103 explicit lock_guard(mutex_type& m); 104 lock_guard(mutex_type& m, adopt_lock_t); 105 ~lock_guard(); 106 107 lock_guard(lock_guard const&) = delete; 108 lock_guard& operator=(lock_guard const&) = delete; 109}; 110 111template <class... MutexTypes> 112class scoped_lock // C++17 113{ 114public: 115 using mutex_type = Mutex; // Only if sizeof...(MutexTypes) == 1 116 117 explicit scoped_lock(MutexTypes&... m); 118 scoped_lock(adopt_lock_t, MutexTypes&... m); 119 ~scoped_lock(); 120 scoped_lock(scoped_lock const&) = delete; 121 scoped_lock& operator=(scoped_lock const&) = delete; 122private: 123 tuple<MutexTypes&...> pm; // exposition only 124}; 125 126template <class Mutex> 127class unique_lock 128{ 129public: 130 typedef Mutex mutex_type; 131 unique_lock() noexcept; 132 explicit unique_lock(mutex_type& m); 133 unique_lock(mutex_type& m, defer_lock_t) noexcept; 134 unique_lock(mutex_type& m, try_to_lock_t); 135 unique_lock(mutex_type& m, adopt_lock_t); 136 template <class Clock, class Duration> 137 unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); 138 template <class Rep, class Period> 139 unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); 140 ~unique_lock(); 141 142 unique_lock(unique_lock const&) = delete; 143 unique_lock& operator=(unique_lock const&) = delete; 144 145 unique_lock(unique_lock&& u) noexcept; 146 unique_lock& operator=(unique_lock&& u) noexcept; 147 148 void lock(); 149 bool try_lock(); 150 151 template <class Rep, class Period> 152 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 153 template <class Clock, class Duration> 154 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 155 156 void unlock(); 157 158 void swap(unique_lock& u) noexcept; 159 mutex_type* release() noexcept; 160 161 bool owns_lock() const noexcept; 162 explicit operator bool () const noexcept; 163 mutex_type* mutex() const noexcept; 164}; 165 166template <class Mutex> 167 void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; 168 169template <class L1, class L2, class... L3> 170 int try_lock(L1&, L2&, L3&...); 171template <class L1, class L2, class... L3> 172 void lock(L1&, L2&, L3&...); 173 174struct once_flag 175{ 176 constexpr once_flag() noexcept; 177 178 once_flag(const once_flag&) = delete; 179 once_flag& operator=(const once_flag&) = delete; 180}; 181 182template<class Callable, class ...Args> 183 void call_once(once_flag& flag, Callable&& func, Args&&... args); 184 185} // std 186 187*/ 188 189#include <__cxx03/__chrono/steady_clock.h> 190#include <__cxx03/__chrono/time_point.h> 191#include <__cxx03/__condition_variable/condition_variable.h> 192#include <__cxx03/__config> 193#include <__cxx03/__memory/shared_ptr.h> 194#include <__cxx03/__mutex/lock_guard.h> 195#include <__cxx03/__mutex/mutex.h> 196#include <__cxx03/__mutex/once_flag.h> 197#include <__cxx03/__mutex/tag_types.h> 198#include <__cxx03/__mutex/unique_lock.h> 199#include <__cxx03/__thread/id.h> 200#include <__cxx03/__thread/support.h> 201#include <__cxx03/__utility/forward.h> 202#include <__cxx03/cstddef> 203#include <__cxx03/limits> 204#include <__cxx03/version> 205 206#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 207# pragma GCC system_header 208#endif 209 210_LIBCPP_PUSH_MACROS 211#include <__cxx03/__undef_macros> 212 213_LIBCPP_BEGIN_NAMESPACE_STD 214 215#ifndef _LIBCPP_HAS_NO_THREADS 216 217class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex { 218 __libcpp_recursive_mutex_t __m_; 219 220public: 221 recursive_mutex(); 222 ~recursive_mutex(); 223 224 recursive_mutex(const recursive_mutex&) = delete; 225 recursive_mutex& operator=(const recursive_mutex&) = delete; 226 227 void lock(); 228 bool try_lock() _NOEXCEPT; 229 void unlock() _NOEXCEPT; 230 231 typedef __libcpp_recursive_mutex_t* native_handle_type; 232 233 _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; } 234}; 235 236class _LIBCPP_EXPORTED_FROM_ABI timed_mutex { 237 mutex __m_; 238 condition_variable __cv_; 239 bool __locked_; 240 241public: 242 timed_mutex(); 243 ~timed_mutex(); 244 245 timed_mutex(const timed_mutex&) = delete; 246 timed_mutex& operator=(const timed_mutex&) = delete; 247 248public: 249 void lock(); 250 bool try_lock() _NOEXCEPT; 251 template <class _Rep, class _Period> 252 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 253 return try_lock_until(chrono::steady_clock::now() + __d); 254 } 255 template <class _Clock, class _Duration> 256 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 257 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 258 void unlock() _NOEXCEPT; 259}; 260 261template <class _Clock, class _Duration> 262bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 263 using namespace chrono; 264 unique_lock<mutex> __lk(__m_); 265 bool __no_timeout = _Clock::now() < __t; 266 while (__no_timeout && __locked_) 267 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 268 if (!__locked_) { 269 __locked_ = true; 270 return true; 271 } 272 return false; 273} 274 275class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex { 276 mutex __m_; 277 condition_variable __cv_; 278 size_t __count_; 279 __thread_id __id_; 280 281public: 282 recursive_timed_mutex(); 283 ~recursive_timed_mutex(); 284 285 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 286 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 287 288 void lock(); 289 bool try_lock() _NOEXCEPT; 290 template <class _Rep, class _Period> 291 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 292 return try_lock_until(chrono::steady_clock::now() + __d); 293 } 294 template <class _Clock, class _Duration> 295 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 296 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 297 void unlock() _NOEXCEPT; 298}; 299 300template <class _Clock, class _Duration> 301bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 302 using namespace chrono; 303 __thread_id __id = this_thread::get_id(); 304 unique_lock<mutex> __lk(__m_); 305 if (__id == __id_) { 306 if (__count_ == numeric_limits<size_t>::max()) 307 return false; 308 ++__count_; 309 return true; 310 } 311 bool __no_timeout = _Clock::now() < __t; 312 while (__no_timeout && __count_ != 0) 313 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 314 if (__count_ == 0) { 315 __count_ = 1; 316 __id_ = __id; 317 return true; 318 } 319 return false; 320} 321 322template <class _L0, class _L1> 323_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { 324 unique_lock<_L0> __u0(__l0, try_to_lock_t()); 325 if (__u0.owns_lock()) { 326 if (__l1.try_lock()) { 327 __u0.release(); 328 return -1; 329 } else 330 return 1; 331 } 332 return 0; 333} 334 335template <class _L0, class _L1> 336_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) { 337 while (true) { 338 { 339 unique_lock<_L0> __u0(__l0); 340 if (__l1.try_lock()) { 341 __u0.release(); 342 break; 343 } 344 } 345 __libcpp_thread_yield(); 346 { 347 unique_lock<_L1> __u1(__l1); 348 if (__l0.try_lock()) { 349 __u1.release(); 350 break; 351 } 352 } 353 __libcpp_thread_yield(); 354 } 355} 356#endif // !_LIBCPP_HAS_NO_THREADS 357 358_LIBCPP_END_NAMESPACE_STD 359 360_LIBCPP_POP_MACROS 361 362#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) 363# include <__cxx03/atomic> 364# include <__cxx03/cstdlib> 365# include <__cxx03/cstring> 366# include <__cxx03/ctime> 367# include <__cxx03/iosfwd> 368# include <__cxx03/new> 369# include <__cxx03/stdexcept> 370# include <__cxx03/system_error> 371# include <__cxx03/type_traits> 372# include <__cxx03/typeinfo> 373#endif 374 375#endif // _LIBCPP___CXX03_MUTEX 376