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