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_MUTEX 11#define _LIBCPP_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 <__chrono/steady_clock.h> 190#include <__chrono/time_point.h> 191#include <__condition_variable/condition_variable.h> 192#include <__config> 193#include <__mutex/lock_guard.h> 194#include <__mutex/mutex.h> 195#include <__mutex/once_flag.h> 196#include <__mutex/tag_types.h> 197#include <__mutex/unique_lock.h> 198#include <__thread/id.h> 199#include <__thread/support.h> 200#include <__utility/forward.h> 201#include <limits> 202#ifndef _LIBCPP_CXX03_LANG 203# include <tuple> 204#endif 205#include <version> 206 207#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 208# pragma GCC system_header 209#endif 210 211_LIBCPP_PUSH_MACROS 212#include <__undef_macros> 213 214_LIBCPP_BEGIN_NAMESPACE_STD 215 216#if _LIBCPP_HAS_THREADS 217 218class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex { 219 __libcpp_recursive_mutex_t __m_; 220 221public: 222 recursive_mutex(); 223 ~recursive_mutex(); 224 225 recursive_mutex(const recursive_mutex&) = delete; 226 recursive_mutex& operator=(const recursive_mutex&) = delete; 227 228 void lock(); 229 bool try_lock() _NOEXCEPT; 230 void unlock() _NOEXCEPT; 231 232 typedef __libcpp_recursive_mutex_t* native_handle_type; 233 234 _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; } 235}; 236 237class _LIBCPP_EXPORTED_FROM_ABI timed_mutex { 238 mutex __m_; 239 condition_variable __cv_; 240 bool __locked_; 241 242public: 243 timed_mutex(); 244 ~timed_mutex(); 245 246 timed_mutex(const timed_mutex&) = delete; 247 timed_mutex& operator=(const timed_mutex&) = delete; 248 249public: 250 void lock(); 251 bool try_lock() _NOEXCEPT; 252 template <class _Rep, class _Period> 253 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 254 return try_lock_until(chrono::steady_clock::now() + __d); 255 } 256 template <class _Clock, class _Duration> 257 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 258 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 259 void unlock() _NOEXCEPT; 260}; 261 262template <class _Clock, class _Duration> 263bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 264 using namespace chrono; 265 unique_lock<mutex> __lk(__m_); 266 bool __no_timeout = _Clock::now() < __t; 267 while (__no_timeout && __locked_) 268 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 269 if (!__locked_) { 270 __locked_ = true; 271 return true; 272 } 273 return false; 274} 275 276class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex { 277 mutex __m_; 278 condition_variable __cv_; 279 size_t __count_; 280 __thread_id __id_; 281 282public: 283 recursive_timed_mutex(); 284 ~recursive_timed_mutex(); 285 286 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 287 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 288 289 void lock(); 290 bool try_lock() _NOEXCEPT; 291 template <class _Rep, class _Period> 292 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 293 return try_lock_until(chrono::steady_clock::now() + __d); 294 } 295 template <class _Clock, class _Duration> 296 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool 297 try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 298 void unlock() _NOEXCEPT; 299}; 300 301template <class _Clock, class _Duration> 302bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 303 using namespace chrono; 304 __thread_id __id = this_thread::get_id(); 305 unique_lock<mutex> __lk(__m_); 306 if (__id == __id_) { 307 if (__count_ == numeric_limits<size_t>::max()) 308 return false; 309 ++__count_; 310 return true; 311 } 312 bool __no_timeout = _Clock::now() < __t; 313 while (__no_timeout && __count_ != 0) 314 __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 315 if (__count_ == 0) { 316 __count_ = 1; 317 __id_ = __id; 318 return true; 319 } 320 return false; 321} 322 323template <class _L0, class _L1> 324_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { 325 unique_lock<_L0> __u0(__l0, try_to_lock_t()); 326 if (__u0.owns_lock()) { 327 if (__l1.try_lock()) { 328 __u0.release(); 329 return -1; 330 } else 331 return 1; 332 } 333 return 0; 334} 335 336# ifndef _LIBCPP_CXX03_LANG 337 338template <class _L0, class _L1, class _L2, class... _L3> 339_LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 340 int __r = 0; 341 unique_lock<_L0> __u0(__l0, try_to_lock); 342 if (__u0.owns_lock()) { 343 __r = std::try_lock(__l1, __l2, __l3...); 344 if (__r == -1) 345 __u0.release(); 346 else 347 ++__r; 348 } 349 return __r; 350} 351 352# endif // _LIBCPP_CXX03_LANG 353 354template <class _L0, class _L1> 355_LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1) { 356 while (true) { 357 { 358 unique_lock<_L0> __u0(__l0); 359 if (__l1.try_lock()) { 360 __u0.release(); 361 break; 362 } 363 } 364 __libcpp_thread_yield(); 365 { 366 unique_lock<_L1> __u1(__l1); 367 if (__l0.try_lock()) { 368 __u1.release(); 369 break; 370 } 371 } 372 __libcpp_thread_yield(); 373 } 374} 375 376# ifndef _LIBCPP_CXX03_LANG 377 378template <class _L0, class _L1, class _L2, class... _L3> 379void __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 380 while (true) { 381 switch (__i) { 382 case 0: { 383 unique_lock<_L0> __u0(__l0); 384 __i = std::try_lock(__l1, __l2, __l3...); 385 if (__i == -1) { 386 __u0.release(); 387 return; 388 } 389 } 390 ++__i; 391 __libcpp_thread_yield(); 392 break; 393 case 1: { 394 unique_lock<_L1> __u1(__l1); 395 __i = std::try_lock(__l2, __l3..., __l0); 396 if (__i == -1) { 397 __u1.release(); 398 return; 399 } 400 } 401 if (__i == sizeof...(_L3) + 1) 402 __i = 0; 403 else 404 __i += 2; 405 __libcpp_thread_yield(); 406 break; 407 default: 408 std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1); 409 return; 410 } 411 } 412} 413 414template <class _L0, class _L1, class _L2, class... _L3> 415inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 416 std::__lock_first(0, __l0, __l1, __l2, __l3...); 417} 418 419# endif // _LIBCPP_CXX03_LANG 420 421# if _LIBCPP_STD_VER >= 17 422template <class... _Mutexes> 423class _LIBCPP_TEMPLATE_VIS scoped_lock; 424 425template <> 426class _LIBCPP_TEMPLATE_VIS scoped_lock<> { 427public: 428 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock() {} 429 ~scoped_lock() = default; 430 431 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t) {} 432 433 scoped_lock(scoped_lock const&) = delete; 434 scoped_lock& operator=(scoped_lock const&) = delete; 435}; 436 437template <class _Mutex> 438class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { 439public: 440 typedef _Mutex mutex_type; 441 442private: 443 mutex_type& __m_; 444 445public: 446 [[nodiscard]] 447 _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 448 : __m_(__m) { 449 __m_.lock(); 450 } 451 452 ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } 453 454 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) 455 _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 456 : __m_(__m) {} 457 458 scoped_lock(scoped_lock const&) = delete; 459 scoped_lock& operator=(scoped_lock const&) = delete; 460}; 461 462template <class... _MArgs> 463class _LIBCPP_TEMPLATE_VIS scoped_lock { 464 static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); 465 typedef tuple<_MArgs&...> _MutexTuple; 466 467public: 468 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(_MArgs&... __margs) : __t_(__margs...) { 469 std::lock(__margs...); 470 } 471 472 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {} 473 474 _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { 475 typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; 476 __unlock_unpack(_Indices{}, __t_); 477 } 478 479 scoped_lock(scoped_lock const&) = delete; 480 scoped_lock& operator=(scoped_lock const&) = delete; 481 482private: 483 template <size_t... _Indx> 484 _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { 485 (std::get<_Indx>(__mt).unlock(), ...); 486 } 487 488 _MutexTuple __t_; 489}; 490_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock); 491 492# endif // _LIBCPP_STD_VER >= 17 493#endif // _LIBCPP_HAS_THREADS 494 495_LIBCPP_END_NAMESPACE_STD 496 497_LIBCPP_POP_MACROS 498 499#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 500# include <atomic> 501# include <concepts> 502# include <cstdlib> 503# include <cstring> 504# include <ctime> 505# include <initializer_list> 506# include <iosfwd> 507# include <new> 508# include <stdexcept> 509# include <system_error> 510# include <type_traits> 511# include <typeinfo> 512#endif 513 514#endif // _LIBCPP_MUTEX 515