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 <__assert> // all public C++ headers provide the assertion handler 190#include <__config> 191#include <__mutex_base> 192#include <__threading_support> 193#include <__utility/forward.h> 194#include <cstdint> 195#include <functional> // TODO: Remove this include 196#include <memory> 197#ifndef _LIBCPP_CXX03_LANG 198# include <tuple> 199#endif 200#include <version> 201 202#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 203# pragma GCC system_header 204#endif 205 206_LIBCPP_PUSH_MACROS 207#include <__undef_macros> 208 209 210_LIBCPP_BEGIN_NAMESPACE_STD 211 212#ifndef _LIBCPP_HAS_NO_THREADS 213 214class _LIBCPP_TYPE_VIS recursive_mutex 215{ 216 __libcpp_recursive_mutex_t __m_; 217 218public: 219 recursive_mutex(); 220 ~recursive_mutex(); 221 222 recursive_mutex(const recursive_mutex&) = delete; 223 recursive_mutex& operator=(const recursive_mutex&) = delete; 224 225 void lock(); 226 bool try_lock() _NOEXCEPT; 227 void unlock() _NOEXCEPT; 228 229 typedef __libcpp_recursive_mutex_t* native_handle_type; 230 231 _LIBCPP_INLINE_VISIBILITY 232 native_handle_type native_handle() {return &__m_;} 233}; 234 235class _LIBCPP_TYPE_VIS timed_mutex 236{ 237 mutex __m_; 238 condition_variable __cv_; 239 bool __locked_; 240public: 241 timed_mutex(); 242 ~timed_mutex(); 243 244 timed_mutex(const timed_mutex&) = delete; 245 timed_mutex& operator=(const timed_mutex&) = delete; 246 247public: 248 void lock(); 249 bool try_lock() _NOEXCEPT; 250 template <class _Rep, class _Period> 251 _LIBCPP_INLINE_VISIBILITY 252 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 253 {return try_lock_until(chrono::steady_clock::now() + __d);} 254 template <class _Clock, class _Duration> 255 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 256 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 257 void unlock() _NOEXCEPT; 258}; 259 260template <class _Clock, class _Duration> 261bool 262timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 263{ 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 { 271 __locked_ = true; 272 return true; 273 } 274 return false; 275} 276 277class _LIBCPP_TYPE_VIS recursive_timed_mutex 278{ 279 mutex __m_; 280 condition_variable __cv_; 281 size_t __count_; 282 __thread_id __id_; 283public: 284 recursive_timed_mutex(); 285 ~recursive_timed_mutex(); 286 287 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 288 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 289 290 void lock(); 291 bool try_lock() _NOEXCEPT; 292 template <class _Rep, class _Period> 293 _LIBCPP_INLINE_VISIBILITY 294 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 295 {return try_lock_until(chrono::steady_clock::now() + __d);} 296 template <class _Clock, class _Duration> 297 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 298 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 299 void unlock() _NOEXCEPT; 300}; 301 302template <class _Clock, class _Duration> 303bool 304recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 305{ 306 using namespace chrono; 307 __thread_id __id = this_thread::get_id(); 308 unique_lock<mutex> lk(__m_); 309 if (__id == __id_) 310 { 311 if (__count_ == numeric_limits<size_t>::max()) 312 return false; 313 ++__count_; 314 return true; 315 } 316 bool no_timeout = _Clock::now() < __t; 317 while (no_timeout && __count_ != 0) 318 no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; 319 if (__count_ == 0) 320 { 321 __count_ = 1; 322 __id_ = __id; 323 return true; 324 } 325 return false; 326} 327 328template <class _L0, class _L1> 329int 330try_lock(_L0& __l0, _L1& __l1) 331{ 332 unique_lock<_L0> __u0(__l0, try_to_lock); 333 if (__u0.owns_lock()) 334 { 335 if (__l1.try_lock()) 336 { 337 __u0.release(); 338 return -1; 339 } 340 else 341 return 1; 342 } 343 return 0; 344} 345 346#ifndef _LIBCPP_CXX03_LANG 347 348template <class _L0, class _L1, class _L2, class... _L3> 349int 350try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) 351{ 352 int __r = 0; 353 unique_lock<_L0> __u0(__l0, try_to_lock); 354 if (__u0.owns_lock()) 355 { 356 __r = try_lock(__l1, __l2, __l3...); 357 if (__r == -1) 358 __u0.release(); 359 else 360 ++__r; 361 } 362 return __r; 363} 364 365#endif // _LIBCPP_CXX03_LANG 366 367template <class _L0, class _L1> 368void 369lock(_L0& __l0, _L1& __l1) 370{ 371 while (true) 372 { 373 { 374 unique_lock<_L0> __u0(__l0); 375 if (__l1.try_lock()) 376 { 377 __u0.release(); 378 break; 379 } 380 } 381 __libcpp_thread_yield(); 382 { 383 unique_lock<_L1> __u1(__l1); 384 if (__l0.try_lock()) 385 { 386 __u1.release(); 387 break; 388 } 389 } 390 __libcpp_thread_yield(); 391 } 392} 393 394#ifndef _LIBCPP_CXX03_LANG 395 396template <class _L0, class _L1, class _L2, class ..._L3> 397void 398__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 399{ 400 while (true) 401 { 402 switch (__i) 403 { 404 case 0: 405 { 406 unique_lock<_L0> __u0(__l0); 407 __i = try_lock(__l1, __l2, __l3...); 408 if (__i == -1) 409 { 410 __u0.release(); 411 return; 412 } 413 } 414 ++__i; 415 __libcpp_thread_yield(); 416 break; 417 case 1: 418 { 419 unique_lock<_L1> __u1(__l1); 420 __i = try_lock(__l2, __l3..., __l0); 421 if (__i == -1) 422 { 423 __u1.release(); 424 return; 425 } 426 } 427 if (__i == sizeof...(_L3) + 1) 428 __i = 0; 429 else 430 __i += 2; 431 __libcpp_thread_yield(); 432 break; 433 default: 434 __lock_first(__i - 2, __l2, __l3..., __l0, __l1); 435 return; 436 } 437 } 438} 439 440template <class _L0, class _L1, class _L2, class ..._L3> 441inline _LIBCPP_INLINE_VISIBILITY 442void 443lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 444{ 445 __lock_first(0, __l0, __l1, __l2, __l3...); 446} 447 448template <class _L0> 449inline _LIBCPP_INLINE_VISIBILITY 450void __unlock(_L0& __l0) { 451 __l0.unlock(); 452} 453 454template <class _L0, class _L1> 455inline _LIBCPP_INLINE_VISIBILITY 456void __unlock(_L0& __l0, _L1& __l1) { 457 __l0.unlock(); 458 __l1.unlock(); 459} 460 461template <class _L0, class _L1, class _L2, class ..._L3> 462inline _LIBCPP_INLINE_VISIBILITY 463void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 464 __l0.unlock(); 465 __l1.unlock(); 466 _VSTD::__unlock(__l2, __l3...); 467} 468 469#endif // _LIBCPP_CXX03_LANG 470 471#if _LIBCPP_STD_VER > 14 472template <class ..._Mutexes> 473class _LIBCPP_TEMPLATE_VIS scoped_lock; 474 475template <> 476class _LIBCPP_TEMPLATE_VIS scoped_lock<> { 477public: 478 explicit scoped_lock() {} 479 ~scoped_lock() = default; 480 481 _LIBCPP_INLINE_VISIBILITY 482 explicit scoped_lock(adopt_lock_t) {} 483 484 scoped_lock(scoped_lock const&) = delete; 485 scoped_lock& operator=(scoped_lock const&) = delete; 486}; 487 488template <class _Mutex> 489class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { 490public: 491 typedef _Mutex mutex_type; 492private: 493 mutex_type& __m_; 494public: 495 explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 496 : __m_(__m) {__m_.lock();} 497 498 ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 499 500 _LIBCPP_INLINE_VISIBILITY 501 explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 502 : __m_(__m) {} 503 504 scoped_lock(scoped_lock const&) = delete; 505 scoped_lock& operator=(scoped_lock const&) = delete; 506}; 507 508template <class ..._MArgs> 509class _LIBCPP_TEMPLATE_VIS scoped_lock 510{ 511 static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); 512 typedef tuple<_MArgs&...> _MutexTuple; 513 514public: 515 _LIBCPP_INLINE_VISIBILITY 516 explicit scoped_lock(_MArgs&... __margs) 517 : __t_(__margs...) 518 { 519 _VSTD::lock(__margs...); 520 } 521 522 _LIBCPP_INLINE_VISIBILITY 523 scoped_lock(adopt_lock_t, _MArgs&... __margs) 524 : __t_(__margs...) 525 { 526 } 527 528 _LIBCPP_INLINE_VISIBILITY 529 ~scoped_lock() { 530 typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; 531 __unlock_unpack(_Indices{}, __t_); 532 } 533 534 scoped_lock(scoped_lock const&) = delete; 535 scoped_lock& operator=(scoped_lock const&) = delete; 536 537private: 538 template <size_t ..._Indx> 539 _LIBCPP_INLINE_VISIBILITY 540 static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { 541 _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); 542 } 543 544 _MutexTuple __t_; 545}; 546 547#endif // _LIBCPP_STD_VER > 14 548#endif // !_LIBCPP_HAS_NO_THREADS 549 550struct _LIBCPP_TEMPLATE_VIS once_flag; 551 552#ifndef _LIBCPP_CXX03_LANG 553 554template<class _Callable, class... _Args> 555_LIBCPP_INLINE_VISIBILITY 556void call_once(once_flag&, _Callable&&, _Args&&...); 557 558#else // _LIBCPP_CXX03_LANG 559 560template<class _Callable> 561_LIBCPP_INLINE_VISIBILITY 562void call_once(once_flag&, _Callable&); 563 564template<class _Callable> 565_LIBCPP_INLINE_VISIBILITY 566void call_once(once_flag&, const _Callable&); 567 568#endif // _LIBCPP_CXX03_LANG 569 570struct _LIBCPP_TEMPLATE_VIS once_flag 571{ 572 _LIBCPP_INLINE_VISIBILITY 573 _LIBCPP_CONSTEXPR 574 once_flag() _NOEXCEPT : __state_(0) {} 575 once_flag(const once_flag&) = delete; 576 once_flag& operator=(const once_flag&) = delete; 577 578#if defined(_LIBCPP_ABI_MICROSOFT) 579 typedef uintptr_t _State_type; 580#else 581 typedef unsigned long _State_type; 582#endif 583 584private: 585 _State_type __state_; 586 587#ifndef _LIBCPP_CXX03_LANG 588 template<class _Callable, class... _Args> 589 friend 590 void call_once(once_flag&, _Callable&&, _Args&&...); 591#else // _LIBCPP_CXX03_LANG 592 template<class _Callable> 593 friend 594 void call_once(once_flag&, _Callable&); 595 596 template<class _Callable> 597 friend 598 void call_once(once_flag&, const _Callable&); 599#endif // _LIBCPP_CXX03_LANG 600}; 601 602#ifndef _LIBCPP_CXX03_LANG 603 604template <class _Fp> 605class __call_once_param 606{ 607 _Fp& __f_; 608public: 609 _LIBCPP_INLINE_VISIBILITY 610 explicit __call_once_param(_Fp& __f) : __f_(__f) {} 611 612 _LIBCPP_INLINE_VISIBILITY 613 void operator()() 614 { 615 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 616 __execute(_Index()); 617 } 618 619private: 620 template <size_t ..._Indices> 621 _LIBCPP_INLINE_VISIBILITY 622 void __execute(__tuple_indices<_Indices...>) 623 { 624 _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); 625 } 626}; 627 628#else 629 630template <class _Fp> 631class __call_once_param 632{ 633 _Fp& __f_; 634public: 635 _LIBCPP_INLINE_VISIBILITY 636 explicit __call_once_param(_Fp& __f) : __f_(__f) {} 637 638 _LIBCPP_INLINE_VISIBILITY 639 void operator()() 640 { 641 __f_(); 642 } 643}; 644 645#endif 646 647template <class _Fp> 648void _LIBCPP_INLINE_VISIBILITY 649__call_once_proxy(void* __vp) 650{ 651 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); 652 (*__p)(); 653} 654 655_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, 656 void (*)(void*)); 657 658#ifndef _LIBCPP_CXX03_LANG 659 660template<class _Callable, class... _Args> 661inline _LIBCPP_INLINE_VISIBILITY 662void 663call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) 664{ 665 if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 666 { 667 typedef tuple<_Callable&&, _Args&&...> _Gp; 668 _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); 669 __call_once_param<_Gp> __p(__f); 670 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); 671 } 672} 673 674#else // _LIBCPP_CXX03_LANG 675 676template<class _Callable> 677inline _LIBCPP_INLINE_VISIBILITY 678void 679call_once(once_flag& __flag, _Callable& __func) 680{ 681 if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 682 { 683 __call_once_param<_Callable> __p(__func); 684 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); 685 } 686} 687 688template<class _Callable> 689inline _LIBCPP_INLINE_VISIBILITY 690void 691call_once(once_flag& __flag, const _Callable& __func) 692{ 693 if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 694 { 695 __call_once_param<const _Callable> __p(__func); 696 __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); 697 } 698} 699 700#endif // _LIBCPP_CXX03_LANG 701 702_LIBCPP_END_NAMESPACE_STD 703 704_LIBCPP_POP_MACROS 705 706#endif // _LIBCPP_MUTEX 707