13e519524SHoward Hinnant// -*- C++ -*- 2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===// 33e519524SHoward Hinnant// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 73e519524SHoward Hinnant// 83e519524SHoward Hinnant//===----------------------------------------------------------------------===// 93e519524SHoward Hinnant 103e519524SHoward Hinnant#ifndef _LIBCPP_MUTEX 113e519524SHoward Hinnant#define _LIBCPP_MUTEX 123e519524SHoward Hinnant 133e519524SHoward Hinnant/* 143e519524SHoward Hinnant mutex synopsis 153e519524SHoward Hinnant 163e519524SHoward Hinnantnamespace std 173e519524SHoward Hinnant{ 183e519524SHoward Hinnant 193e519524SHoward Hinnantclass mutex 203e519524SHoward Hinnant{ 213e519524SHoward Hinnantpublic: 2202e610efSHoward Hinnant constexpr mutex() noexcept; 233e519524SHoward Hinnant ~mutex(); 243e519524SHoward Hinnant 253e519524SHoward Hinnant mutex(const mutex&) = delete; 263e519524SHoward Hinnant mutex& operator=(const mutex&) = delete; 273e519524SHoward Hinnant 283e519524SHoward Hinnant void lock(); 293e519524SHoward Hinnant bool try_lock(); 303e519524SHoward Hinnant void unlock(); 313e519524SHoward Hinnant 323e519524SHoward Hinnant typedef pthread_mutex_t* native_handle_type; 333e519524SHoward Hinnant native_handle_type native_handle(); 343e519524SHoward Hinnant}; 353e519524SHoward Hinnant 363e519524SHoward Hinnantclass recursive_mutex 373e519524SHoward Hinnant{ 383e519524SHoward Hinnantpublic: 393e519524SHoward Hinnant recursive_mutex(); 403e519524SHoward Hinnant ~recursive_mutex(); 413e519524SHoward Hinnant 423e519524SHoward Hinnant recursive_mutex(const recursive_mutex&) = delete; 433e519524SHoward Hinnant recursive_mutex& operator=(const recursive_mutex&) = delete; 443e519524SHoward Hinnant 453e519524SHoward Hinnant void lock(); 4602e610efSHoward Hinnant bool try_lock() noexcept; 473e519524SHoward Hinnant void unlock(); 483e519524SHoward Hinnant 493e519524SHoward Hinnant typedef pthread_mutex_t* native_handle_type; 503e519524SHoward Hinnant native_handle_type native_handle(); 513e519524SHoward Hinnant}; 523e519524SHoward Hinnant 533e519524SHoward Hinnantclass timed_mutex 543e519524SHoward Hinnant{ 553e519524SHoward Hinnantpublic: 563e519524SHoward Hinnant timed_mutex(); 573e519524SHoward Hinnant ~timed_mutex(); 583e519524SHoward Hinnant 593e519524SHoward Hinnant timed_mutex(const timed_mutex&) = delete; 603e519524SHoward Hinnant timed_mutex& operator=(const timed_mutex&) = delete; 613e519524SHoward Hinnant 623e519524SHoward Hinnant void lock(); 633e519524SHoward Hinnant bool try_lock(); 643e519524SHoward Hinnant template <class Rep, class Period> 653e519524SHoward Hinnant bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 663e519524SHoward Hinnant template <class Clock, class Duration> 673e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 683e519524SHoward Hinnant void unlock(); 693e519524SHoward Hinnant}; 703e519524SHoward Hinnant 713e519524SHoward Hinnantclass recursive_timed_mutex 723e519524SHoward Hinnant{ 733e519524SHoward Hinnantpublic: 743e519524SHoward Hinnant recursive_timed_mutex(); 753e519524SHoward Hinnant ~recursive_timed_mutex(); 763e519524SHoward Hinnant 773e519524SHoward Hinnant recursive_timed_mutex(const recursive_timed_mutex&) = delete; 783e519524SHoward Hinnant recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 793e519524SHoward Hinnant 803e519524SHoward Hinnant void lock(); 8102e610efSHoward Hinnant bool try_lock() noexcept; 823e519524SHoward Hinnant template <class Rep, class Period> 833e519524SHoward Hinnant bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 843e519524SHoward Hinnant template <class Clock, class Duration> 853e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 863e519524SHoward Hinnant void unlock(); 873e519524SHoward Hinnant}; 883e519524SHoward Hinnant 89e16f2cb6SLouis Dionnestruct defer_lock_t { explicit defer_lock_t() = default; }; 90e16f2cb6SLouis Dionnestruct try_to_lock_t { explicit try_to_lock_t() = default; }; 91e16f2cb6SLouis Dionnestruct adopt_lock_t { explicit adopt_lock_t() = default; }; 923e519524SHoward Hinnant 9340a01d53SMarshall Clowinline constexpr defer_lock_t defer_lock{}; 9440a01d53SMarshall Clowinline constexpr try_to_lock_t try_to_lock{}; 9540a01d53SMarshall Clowinline constexpr adopt_lock_t adopt_lock{}; 963e519524SHoward Hinnant 973e519524SHoward Hinnanttemplate <class Mutex> 983e519524SHoward Hinnantclass lock_guard 993e519524SHoward Hinnant{ 1003e519524SHoward Hinnantpublic: 1013e519524SHoward Hinnant typedef Mutex mutex_type; 1023e519524SHoward Hinnant 1033e519524SHoward Hinnant explicit lock_guard(mutex_type& m); 1043e519524SHoward Hinnant lock_guard(mutex_type& m, adopt_lock_t); 1053e519524SHoward Hinnant ~lock_guard(); 1063e519524SHoward Hinnant 1073e519524SHoward Hinnant lock_guard(lock_guard const&) = delete; 1083e519524SHoward Hinnant lock_guard& operator=(lock_guard const&) = delete; 1093e519524SHoward Hinnant}; 1103e519524SHoward Hinnant 1116015dd11SMarshall Clowtemplate <class... MutexTypes> 1126015dd11SMarshall Clowclass scoped_lock // C++17 11348f35e07SEric Fiselier{ 11448f35e07SEric Fiselierpublic: 1157ad00511SJoe Loser using mutex_type = Mutex; // Only if sizeof...(MutexTypes) == 1 1166015dd11SMarshall Clow 1176015dd11SMarshall Clow explicit scoped_lock(MutexTypes&... m); 11888c893ccSMarshall Clow scoped_lock(adopt_lock_t, MutexTypes&... m); 1196015dd11SMarshall Clow ~scoped_lock(); 1206015dd11SMarshall Clow scoped_lock(scoped_lock const&) = delete; 1216015dd11SMarshall Clow scoped_lock& operator=(scoped_lock const&) = delete; 12248f35e07SEric Fiselierprivate: 12348f35e07SEric Fiselier tuple<MutexTypes&...> pm; // exposition only 12448f35e07SEric Fiselier}; 12548f35e07SEric Fiselier 1263e519524SHoward Hinnanttemplate <class Mutex> 1273e519524SHoward Hinnantclass unique_lock 1283e519524SHoward Hinnant{ 1293e519524SHoward Hinnantpublic: 1303e519524SHoward Hinnant typedef Mutex mutex_type; 13102e610efSHoward Hinnant unique_lock() noexcept; 1323e519524SHoward Hinnant explicit unique_lock(mutex_type& m); 13302e610efSHoward Hinnant unique_lock(mutex_type& m, defer_lock_t) noexcept; 1343e519524SHoward Hinnant unique_lock(mutex_type& m, try_to_lock_t); 1353e519524SHoward Hinnant unique_lock(mutex_type& m, adopt_lock_t); 1363e519524SHoward Hinnant template <class Clock, class Duration> 1373e519524SHoward Hinnant unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); 1383e519524SHoward Hinnant template <class Rep, class Period> 1393e519524SHoward Hinnant unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); 1403e519524SHoward Hinnant ~unique_lock(); 1413e519524SHoward Hinnant 1423e519524SHoward Hinnant unique_lock(unique_lock const&) = delete; 1433e519524SHoward Hinnant unique_lock& operator=(unique_lock const&) = delete; 1443e519524SHoward Hinnant 14502e610efSHoward Hinnant unique_lock(unique_lock&& u) noexcept; 14602e610efSHoward Hinnant unique_lock& operator=(unique_lock&& u) noexcept; 1473e519524SHoward Hinnant 1483e519524SHoward Hinnant void lock(); 1493e519524SHoward Hinnant bool try_lock(); 1503e519524SHoward Hinnant 1513e519524SHoward Hinnant template <class Rep, class Period> 1523e519524SHoward Hinnant bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 1533e519524SHoward Hinnant template <class Clock, class Duration> 1543e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 1553e519524SHoward Hinnant 1563e519524SHoward Hinnant void unlock(); 1573e519524SHoward Hinnant 15802e610efSHoward Hinnant void swap(unique_lock& u) noexcept; 15902e610efSHoward Hinnant mutex_type* release() noexcept; 1603e519524SHoward Hinnant 16102e610efSHoward Hinnant bool owns_lock() const noexcept; 16202e610efSHoward Hinnant explicit operator bool () const noexcept; 16302e610efSHoward Hinnant mutex_type* mutex() const noexcept; 1643e519524SHoward Hinnant}; 1653e519524SHoward Hinnant 1663e519524SHoward Hinnanttemplate <class Mutex> 16702e610efSHoward Hinnant void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; 1683e519524SHoward Hinnant 1693e519524SHoward Hinnanttemplate <class L1, class L2, class... L3> 1703e519524SHoward Hinnant int try_lock(L1&, L2&, L3&...); 1713e519524SHoward Hinnanttemplate <class L1, class L2, class... L3> 1723e519524SHoward Hinnant void lock(L1&, L2&, L3&...); 1733e519524SHoward Hinnant 1743e519524SHoward Hinnantstruct once_flag 1753e519524SHoward Hinnant{ 17602e610efSHoward Hinnant constexpr once_flag() noexcept; 1773e519524SHoward Hinnant 1783e519524SHoward Hinnant once_flag(const once_flag&) = delete; 1793e519524SHoward Hinnant once_flag& operator=(const once_flag&) = delete; 1803e519524SHoward Hinnant}; 1813e519524SHoward Hinnant 1823e519524SHoward Hinnanttemplate<class Callable, class ...Args> 1833e519524SHoward Hinnant void call_once(once_flag& flag, Callable&& func, Args&&... args); 1843e519524SHoward Hinnant 1853e519524SHoward Hinnant} // std 1863e519524SHoward Hinnant 1873e519524SHoward Hinnant*/ 1883e519524SHoward Hinnant 189385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler 1903e519524SHoward Hinnant#include <__config> 1913e519524SHoward Hinnant#include <__mutex_base> 192bfbd73f8SArthur O'Dwyer#include <__threading_support> 1936adbc83eSChristopher Di Bella#include <__utility/forward.h> 1940fd00a58SNico Weber#include <cstdint> 1951faf289eSEric Fiselier#include <memory> 196e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 197872a9116SHoward Hinnant# include <tuple> 198872a9116SHoward Hinnant#endif 199f56972e2SMarshall Clow#include <version> 2003e519524SHoward Hinnant 201*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES 202*de4a57cbSLouis Dionne# include <functional> 203*de4a57cbSLouis Dionne#endif 204*de4a57cbSLouis Dionne 205073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2063e519524SHoward Hinnant# pragma GCC system_header 207073458b1SHoward Hinnant#endif 2083e519524SHoward Hinnant 209a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS 210a016efb1SEric Fiselier#include <__undef_macros> 211a016efb1SEric Fiselier 212a016efb1SEric Fiselier 2133e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD 2143e519524SHoward Hinnant 215b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS 216b3fcc67fSJonathan Roelofs 2176e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_mutex 2183e519524SHoward Hinnant{ 21958a0dceeSSaleem Abdulrasool __libcpp_recursive_mutex_t __m_; 2203e519524SHoward Hinnant 2213e519524SHoward Hinnantpublic: 2223e519524SHoward Hinnant recursive_mutex(); 2233e519524SHoward Hinnant ~recursive_mutex(); 2243e519524SHoward Hinnant 225feb80aa9SNikolas Klauser recursive_mutex(const recursive_mutex&) = delete; 226feb80aa9SNikolas Klauser recursive_mutex& operator=(const recursive_mutex&) = delete; 2273e519524SHoward Hinnant 2283e519524SHoward Hinnant void lock(); 22902e610efSHoward Hinnant bool try_lock() _NOEXCEPT; 23002e610efSHoward Hinnant void unlock() _NOEXCEPT; 2313e519524SHoward Hinnant 23258a0dceeSSaleem Abdulrasool typedef __libcpp_recursive_mutex_t* native_handle_type; 23358a0dceeSSaleem Abdulrasool 234392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2353e519524SHoward Hinnant native_handle_type native_handle() {return &__m_;} 2363e519524SHoward Hinnant}; 2373e519524SHoward Hinnant 2386e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS timed_mutex 2393e519524SHoward Hinnant{ 2403e519524SHoward Hinnant mutex __m_; 2413e519524SHoward Hinnant condition_variable __cv_; 2423e519524SHoward Hinnant bool __locked_; 2433e519524SHoward Hinnantpublic: 2443e519524SHoward Hinnant timed_mutex(); 2453e519524SHoward Hinnant ~timed_mutex(); 2463e519524SHoward Hinnant 247feb80aa9SNikolas Klauser timed_mutex(const timed_mutex&) = delete; 248feb80aa9SNikolas Klauser timed_mutex& operator=(const timed_mutex&) = delete; 2493e519524SHoward Hinnant 2503e519524SHoward Hinnantpublic: 2513e519524SHoward Hinnant void lock(); 25202e610efSHoward Hinnant bool try_lock() _NOEXCEPT; 2533e519524SHoward Hinnant template <class _Rep, class _Period> 254392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2553e519524SHoward Hinnant bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2563dc6455fSHoward Hinnant {return try_lock_until(chrono::steady_clock::now() + __d);} 2573e519524SHoward Hinnant template <class _Clock, class _Duration> 258bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2593e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 26002e610efSHoward Hinnant void unlock() _NOEXCEPT; 2613e519524SHoward Hinnant}; 2623e519524SHoward Hinnant 2633e519524SHoward Hinnanttemplate <class _Clock, class _Duration> 2643e519524SHoward Hinnantbool 2653e519524SHoward Hinnanttimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 2663e519524SHoward Hinnant{ 2673e519524SHoward Hinnant using namespace chrono; 2683e519524SHoward Hinnant unique_lock<mutex> __lk(__m_); 2693e519524SHoward Hinnant bool no_timeout = _Clock::now() < __t; 2703e519524SHoward Hinnant while (no_timeout && __locked_) 2713e519524SHoward Hinnant no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 2723e519524SHoward Hinnant if (!__locked_) 2733e519524SHoward Hinnant { 2743e519524SHoward Hinnant __locked_ = true; 2753e519524SHoward Hinnant return true; 2763e519524SHoward Hinnant } 2773e519524SHoward Hinnant return false; 2783e519524SHoward Hinnant} 2793e519524SHoward Hinnant 2806e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_timed_mutex 2813e519524SHoward Hinnant{ 2823e519524SHoward Hinnant mutex __m_; 2833e519524SHoward Hinnant condition_variable __cv_; 2843e519524SHoward Hinnant size_t __count_; 2852b1d4254SMarshall Clow __thread_id __id_; 2863e519524SHoward Hinnantpublic: 2873e519524SHoward Hinnant recursive_timed_mutex(); 2883e519524SHoward Hinnant ~recursive_timed_mutex(); 2893e519524SHoward Hinnant 290feb80aa9SNikolas Klauser recursive_timed_mutex(const recursive_timed_mutex&) = delete; 291feb80aa9SNikolas Klauser recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 2923e519524SHoward Hinnant 2933e519524SHoward Hinnant void lock(); 29402e610efSHoward Hinnant bool try_lock() _NOEXCEPT; 2953e519524SHoward Hinnant template <class _Rep, class _Period> 296392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2973e519524SHoward Hinnant bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2983dc6455fSHoward Hinnant {return try_lock_until(chrono::steady_clock::now() + __d);} 2993e519524SHoward Hinnant template <class _Clock, class _Duration> 300bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 3013e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 30202e610efSHoward Hinnant void unlock() _NOEXCEPT; 3033e519524SHoward Hinnant}; 3043e519524SHoward Hinnant 3053e519524SHoward Hinnanttemplate <class _Clock, class _Duration> 3063e519524SHoward Hinnantbool 3073e519524SHoward Hinnantrecursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 3083e519524SHoward Hinnant{ 3093e519524SHoward Hinnant using namespace chrono; 3102b1d4254SMarshall Clow __thread_id __id = this_thread::get_id(); 3113e519524SHoward Hinnant unique_lock<mutex> lk(__m_); 3122b1d4254SMarshall Clow if (__id == __id_) 3133e519524SHoward Hinnant { 3143e519524SHoward Hinnant if (__count_ == numeric_limits<size_t>::max()) 3153e519524SHoward Hinnant return false; 3163e519524SHoward Hinnant ++__count_; 3173e519524SHoward Hinnant return true; 3183e519524SHoward Hinnant } 3193e519524SHoward Hinnant bool no_timeout = _Clock::now() < __t; 3203e519524SHoward Hinnant while (no_timeout && __count_ != 0) 3213e519524SHoward Hinnant no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; 3223e519524SHoward Hinnant if (__count_ == 0) 3233e519524SHoward Hinnant { 3243e519524SHoward Hinnant __count_ = 1; 3253e519524SHoward Hinnant __id_ = __id; 3263e519524SHoward Hinnant return true; 3273e519524SHoward Hinnant } 3283e519524SHoward Hinnant return false; 3293e519524SHoward Hinnant} 3303e519524SHoward Hinnant 3313e519524SHoward Hinnanttemplate <class _L0, class _L1> 3323e519524SHoward Hinnantint 3333e519524SHoward Hinnanttry_lock(_L0& __l0, _L1& __l1) 3343e519524SHoward Hinnant{ 3353e519524SHoward Hinnant unique_lock<_L0> __u0(__l0, try_to_lock); 3363e519524SHoward Hinnant if (__u0.owns_lock()) 3373e519524SHoward Hinnant { 3383e519524SHoward Hinnant if (__l1.try_lock()) 3393e519524SHoward Hinnant { 3403e519524SHoward Hinnant __u0.release(); 3413e519524SHoward Hinnant return -1; 3423e519524SHoward Hinnant } 3433e519524SHoward Hinnant else 3443e519524SHoward Hinnant return 1; 3453e519524SHoward Hinnant } 3463e519524SHoward Hinnant return 0; 3473e519524SHoward Hinnant} 3483e519524SHoward Hinnant 349e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 3503e519524SHoward Hinnant 3513e519524SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class... _L3> 3523e519524SHoward Hinnantint 3533e519524SHoward Hinnanttry_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) 3543e519524SHoward Hinnant{ 3553e519524SHoward Hinnant int __r = 0; 3563e519524SHoward Hinnant unique_lock<_L0> __u0(__l0, try_to_lock); 3573e519524SHoward Hinnant if (__u0.owns_lock()) 3583e519524SHoward Hinnant { 3593e519524SHoward Hinnant __r = try_lock(__l1, __l2, __l3...); 3603e519524SHoward Hinnant if (__r == -1) 3613e519524SHoward Hinnant __u0.release(); 3623e519524SHoward Hinnant else 3633e519524SHoward Hinnant ++__r; 3643e519524SHoward Hinnant } 3653e519524SHoward Hinnant return __r; 3663e519524SHoward Hinnant} 3673e519524SHoward Hinnant 368e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 3693e519524SHoward Hinnant 3703e519524SHoward Hinnanttemplate <class _L0, class _L1> 3713e519524SHoward Hinnantvoid 3723e519524SHoward Hinnantlock(_L0& __l0, _L1& __l1) 3733e519524SHoward Hinnant{ 3743e519524SHoward Hinnant while (true) 3753e519524SHoward Hinnant { 3763e519524SHoward Hinnant { 3773e519524SHoward Hinnant unique_lock<_L0> __u0(__l0); 3783e519524SHoward Hinnant if (__l1.try_lock()) 3793e519524SHoward Hinnant { 3803e519524SHoward Hinnant __u0.release(); 3813e519524SHoward Hinnant break; 3823e519524SHoward Hinnant } 3833e519524SHoward Hinnant } 384c7e4239fSAsiri Rathnayake __libcpp_thread_yield(); 3853e519524SHoward Hinnant { 3863e519524SHoward Hinnant unique_lock<_L1> __u1(__l1); 3873e519524SHoward Hinnant if (__l0.try_lock()) 3883e519524SHoward Hinnant { 3893e519524SHoward Hinnant __u1.release(); 3903e519524SHoward Hinnant break; 3913e519524SHoward Hinnant } 3923e519524SHoward Hinnant } 393c7e4239fSAsiri Rathnayake __libcpp_thread_yield(); 3943e519524SHoward Hinnant } 3953e519524SHoward Hinnant} 3963e519524SHoward Hinnant 397e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 3983e519524SHoward Hinnant 39959a7dc95SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class ..._L3> 4003e519524SHoward Hinnantvoid 40159a7dc95SHoward Hinnant__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 4023e519524SHoward Hinnant{ 4033e519524SHoward Hinnant while (true) 4043e519524SHoward Hinnant { 4053e519524SHoward Hinnant switch (__i) 4063e519524SHoward Hinnant { 4073e519524SHoward Hinnant case 0: 4083e519524SHoward Hinnant { 4093e519524SHoward Hinnant unique_lock<_L0> __u0(__l0); 41059a7dc95SHoward Hinnant __i = try_lock(__l1, __l2, __l3...); 4113e519524SHoward Hinnant if (__i == -1) 4123e519524SHoward Hinnant { 4133e519524SHoward Hinnant __u0.release(); 4143e519524SHoward Hinnant return; 4153e519524SHoward Hinnant } 4163e519524SHoward Hinnant } 4173e519524SHoward Hinnant ++__i; 418c7e4239fSAsiri Rathnayake __libcpp_thread_yield(); 4193e519524SHoward Hinnant break; 4203e519524SHoward Hinnant case 1: 4213e519524SHoward Hinnant { 4223e519524SHoward Hinnant unique_lock<_L1> __u1(__l1); 42359a7dc95SHoward Hinnant __i = try_lock(__l2, __l3..., __l0); 4243e519524SHoward Hinnant if (__i == -1) 4253e519524SHoward Hinnant { 4263e519524SHoward Hinnant __u1.release(); 4273e519524SHoward Hinnant return; 4283e519524SHoward Hinnant } 4293e519524SHoward Hinnant } 43059a7dc95SHoward Hinnant if (__i == sizeof...(_L3) + 1) 4313e519524SHoward Hinnant __i = 0; 4323e519524SHoward Hinnant else 4333e519524SHoward Hinnant __i += 2; 434c7e4239fSAsiri Rathnayake __libcpp_thread_yield(); 4353e519524SHoward Hinnant break; 4363e519524SHoward Hinnant default: 43759a7dc95SHoward Hinnant __lock_first(__i - 2, __l2, __l3..., __l0, __l1); 4383e519524SHoward Hinnant return; 4393e519524SHoward Hinnant } 4403e519524SHoward Hinnant } 4413e519524SHoward Hinnant} 4423e519524SHoward Hinnant 44359a7dc95SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class ..._L3> 444392183f9SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 4453e519524SHoward Hinnantvoid 44659a7dc95SHoward Hinnantlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 4473e519524SHoward Hinnant{ 44859a7dc95SHoward Hinnant __lock_first(0, __l0, __l1, __l2, __l3...); 4493e519524SHoward Hinnant} 4503e519524SHoward Hinnant 45148f35e07SEric Fiseliertemplate <class _L0> 45248f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 45348f35e07SEric Fiseliervoid __unlock(_L0& __l0) { 45448f35e07SEric Fiselier __l0.unlock(); 45548f35e07SEric Fiselier} 45648f35e07SEric Fiselier 45748f35e07SEric Fiseliertemplate <class _L0, class _L1> 45848f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 45948f35e07SEric Fiseliervoid __unlock(_L0& __l0, _L1& __l1) { 46048f35e07SEric Fiselier __l0.unlock(); 46148f35e07SEric Fiselier __l1.unlock(); 46248f35e07SEric Fiselier} 46348f35e07SEric Fiselier 46448f35e07SEric Fiseliertemplate <class _L0, class _L1, class _L2, class ..._L3> 46548f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 46648f35e07SEric Fiseliervoid __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 46748f35e07SEric Fiselier __l0.unlock(); 46848f35e07SEric Fiselier __l1.unlock(); 46948f35e07SEric Fiselier _VSTD::__unlock(__l2, __l3...); 47048f35e07SEric Fiselier} 47148f35e07SEric Fiselier 472e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 4733e519524SHoward Hinnant 4749f3fd40aSMarshall Clow#if _LIBCPP_STD_VER > 14 4759f3fd40aSMarshall Clowtemplate <class ..._Mutexes> 4769f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock; 4779f3fd40aSMarshall Clow 4789f3fd40aSMarshall Clowtemplate <> 4799f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock<> { 4809f3fd40aSMarshall Clowpublic: 4819f3fd40aSMarshall Clow explicit scoped_lock() {} 4829f3fd40aSMarshall Clow ~scoped_lock() = default; 4839f3fd40aSMarshall Clow 4849f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 4859f3fd40aSMarshall Clow explicit scoped_lock(adopt_lock_t) {} 4869f3fd40aSMarshall Clow 4879f3fd40aSMarshall Clow scoped_lock(scoped_lock const&) = delete; 4889f3fd40aSMarshall Clow scoped_lock& operator=(scoped_lock const&) = delete; 4899f3fd40aSMarshall Clow}; 4909f3fd40aSMarshall Clow 4919f3fd40aSMarshall Clowtemplate <class _Mutex> 4927f208f02SAaron Puchertclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { 4939f3fd40aSMarshall Clowpublic: 4949f3fd40aSMarshall Clow typedef _Mutex mutex_type; 4959f3fd40aSMarshall Clowprivate: 4969f3fd40aSMarshall Clow mutex_type& __m_; 4979f3fd40aSMarshall Clowpublic: 4989f3fd40aSMarshall Clow explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 4999f3fd40aSMarshall Clow : __m_(__m) {__m_.lock();} 5009f3fd40aSMarshall Clow 5019f3fd40aSMarshall Clow ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 5029f3fd40aSMarshall Clow 5039f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 50488c893ccSMarshall Clow explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 5059f3fd40aSMarshall Clow : __m_(__m) {} 5069f3fd40aSMarshall Clow 5079f3fd40aSMarshall Clow scoped_lock(scoped_lock const&) = delete; 5089f3fd40aSMarshall Clow scoped_lock& operator=(scoped_lock const&) = delete; 5099f3fd40aSMarshall Clow}; 5109f3fd40aSMarshall Clow 5119f3fd40aSMarshall Clowtemplate <class ..._MArgs> 5129f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock 5139f3fd40aSMarshall Clow{ 5149f3fd40aSMarshall Clow static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); 5159f3fd40aSMarshall Clow typedef tuple<_MArgs&...> _MutexTuple; 5169f3fd40aSMarshall Clow 5179f3fd40aSMarshall Clowpublic: 5189f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 5199f3fd40aSMarshall Clow explicit scoped_lock(_MArgs&... __margs) 5209f3fd40aSMarshall Clow : __t_(__margs...) 5219f3fd40aSMarshall Clow { 5229f3fd40aSMarshall Clow _VSTD::lock(__margs...); 5239f3fd40aSMarshall Clow } 5249f3fd40aSMarshall Clow 5259f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 52688c893ccSMarshall Clow scoped_lock(adopt_lock_t, _MArgs&... __margs) 5279f3fd40aSMarshall Clow : __t_(__margs...) 5289f3fd40aSMarshall Clow { 5299f3fd40aSMarshall Clow } 5309f3fd40aSMarshall Clow 5319f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 5329f3fd40aSMarshall Clow ~scoped_lock() { 5339f3fd40aSMarshall Clow typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; 5349f3fd40aSMarshall Clow __unlock_unpack(_Indices{}, __t_); 5359f3fd40aSMarshall Clow } 5369f3fd40aSMarshall Clow 5379f3fd40aSMarshall Clow scoped_lock(scoped_lock const&) = delete; 5389f3fd40aSMarshall Clow scoped_lock& operator=(scoped_lock const&) = delete; 5399f3fd40aSMarshall Clow 5409f3fd40aSMarshall Clowprivate: 5419f3fd40aSMarshall Clow template <size_t ..._Indx> 5429f3fd40aSMarshall Clow _LIBCPP_INLINE_VISIBILITY 5439f3fd40aSMarshall Clow static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { 5449f3fd40aSMarshall Clow _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); 5459f3fd40aSMarshall Clow } 5469f3fd40aSMarshall Clow 5479f3fd40aSMarshall Clow _MutexTuple __t_; 5489f3fd40aSMarshall Clow}; 5499f3fd40aSMarshall Clow 5509f3fd40aSMarshall Clow#endif // _LIBCPP_STD_VER > 14 551b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS 552b3fcc67fSJonathan Roelofs 553e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS once_flag; 5543e519524SHoward Hinnant 555e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 5563e519524SHoward Hinnant 5573e519524SHoward Hinnanttemplate<class _Callable, class... _Args> 558aeb85680SHoward Hinnant_LIBCPP_INLINE_VISIBILITY 5593e519524SHoward Hinnantvoid call_once(once_flag&, _Callable&&, _Args&&...); 5603e519524SHoward Hinnant 561e11fb13bSEric Fiselier#else // _LIBCPP_CXX03_LANG 5623e519524SHoward Hinnant 5633e519524SHoward Hinnanttemplate<class _Callable> 564aeb85680SHoward Hinnant_LIBCPP_INLINE_VISIBILITY 565793f59e7SEric Fiseliervoid call_once(once_flag&, _Callable&); 566793f59e7SEric Fiselier 567793f59e7SEric Fiseliertemplate<class _Callable> 568793f59e7SEric Fiselier_LIBCPP_INLINE_VISIBILITY 569793f59e7SEric Fiseliervoid call_once(once_flag&, const _Callable&); 5703e519524SHoward Hinnant 571e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 5723e519524SHoward Hinnant 573e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS once_flag 5743e519524SHoward Hinnant{ 575392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 57602e610efSHoward Hinnant _LIBCPP_CONSTEXPR 57702e610efSHoward Hinnant once_flag() _NOEXCEPT : __state_(0) {} 578feb80aa9SNikolas Klauser once_flag(const once_flag&) = delete; 579feb80aa9SNikolas Klauser once_flag& operator=(const once_flag&) = delete; 5803e519524SHoward Hinnant 5810fd00a58SNico Weber#if defined(_LIBCPP_ABI_MICROSOFT) 5820fd00a58SNico Weber typedef uintptr_t _State_type; 5830fd00a58SNico Weber#else 5840fd00a58SNico Weber typedef unsigned long _State_type; 5850fd00a58SNico Weber#endif 5860fd00a58SNico Weber 5873e519524SHoward Hinnantprivate: 5880fd00a58SNico Weber _State_type __state_; 5893e519524SHoward Hinnant 590e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 5913e519524SHoward Hinnant template<class _Callable, class... _Args> 5923e519524SHoward Hinnant friend 5933e519524SHoward Hinnant void call_once(once_flag&, _Callable&&, _Args&&...); 594e11fb13bSEric Fiselier#else // _LIBCPP_CXX03_LANG 5953e519524SHoward Hinnant template<class _Callable> 5963e519524SHoward Hinnant friend 597793f59e7SEric Fiselier void call_once(once_flag&, _Callable&); 598793f59e7SEric Fiselier 599793f59e7SEric Fiselier template<class _Callable> 600793f59e7SEric Fiselier friend 601793f59e7SEric Fiselier void call_once(once_flag&, const _Callable&); 602e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 6033e519524SHoward Hinnant}; 6043e519524SHoward Hinnant 605e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 606872a9116SHoward Hinnant 607c003db1fSHoward Hinnanttemplate <class _Fp> 608872a9116SHoward Hinnantclass __call_once_param 609872a9116SHoward Hinnant{ 610793f59e7SEric Fiselier _Fp& __f_; 611872a9116SHoward Hinnantpublic: 612872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 613793f59e7SEric Fiselier explicit __call_once_param(_Fp& __f) : __f_(__f) {} 614872a9116SHoward Hinnant 615872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 616872a9116SHoward Hinnant void operator()() 617872a9116SHoward Hinnant { 618c003db1fSHoward Hinnant typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 619872a9116SHoward Hinnant __execute(_Index()); 620872a9116SHoward Hinnant } 621872a9116SHoward Hinnant 622872a9116SHoward Hinnantprivate: 623872a9116SHoward Hinnant template <size_t ..._Indices> 624872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 625872a9116SHoward Hinnant void __execute(__tuple_indices<_Indices...>) 626872a9116SHoward Hinnant { 627781c476cSArthur O'Dwyer _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); 628872a9116SHoward Hinnant } 629872a9116SHoward Hinnant}; 630872a9116SHoward Hinnant 631872a9116SHoward Hinnant#else 632872a9116SHoward Hinnant 633c003db1fSHoward Hinnanttemplate <class _Fp> 6343e519524SHoward Hinnantclass __call_once_param 6353e519524SHoward Hinnant{ 636793f59e7SEric Fiselier _Fp& __f_; 6373e519524SHoward Hinnantpublic: 638392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 639793f59e7SEric Fiselier explicit __call_once_param(_Fp& __f) : __f_(__f) {} 6403e519524SHoward Hinnant 641392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 6423e519524SHoward Hinnant void operator()() 6433e519524SHoward Hinnant { 6443e519524SHoward Hinnant __f_(); 6453e519524SHoward Hinnant } 6463e519524SHoward Hinnant}; 6473e519524SHoward Hinnant 648872a9116SHoward Hinnant#endif 649872a9116SHoward Hinnant 650c003db1fSHoward Hinnanttemplate <class _Fp> 65148b7068bSLouis Dionnevoid _LIBCPP_INLINE_VISIBILITY 6523e519524SHoward Hinnant__call_once_proxy(void* __vp) 6533e519524SHoward Hinnant{ 654c003db1fSHoward Hinnant __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); 6553e519524SHoward Hinnant (*__p)(); 6563e519524SHoward Hinnant} 6573e519524SHoward Hinnant 6580fd00a58SNico Weber_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, 6590fd00a58SNico Weber void (*)(void*)); 6603e519524SHoward Hinnant 661e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 6623e519524SHoward Hinnant 6633e519524SHoward Hinnanttemplate<class _Callable, class... _Args> 6643e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 6653e519524SHoward Hinnantvoid 6663e519524SHoward Hinnantcall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) 6673e519524SHoward Hinnant{ 6680fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 6693e519524SHoward Hinnant { 670793f59e7SEric Fiselier typedef tuple<_Callable&&, _Args&&...> _Gp; 671793f59e7SEric Fiselier _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); 672793f59e7SEric Fiselier __call_once_param<_Gp> __p(__f); 673c003db1fSHoward Hinnant __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); 6743e519524SHoward Hinnant } 6753e519524SHoward Hinnant} 6763e519524SHoward Hinnant 677e11fb13bSEric Fiselier#else // _LIBCPP_CXX03_LANG 6783e519524SHoward Hinnant 6793e519524SHoward Hinnanttemplate<class _Callable> 6803e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 6813e519524SHoward Hinnantvoid 682793f59e7SEric Fiseliercall_once(once_flag& __flag, _Callable& __func) 6833e519524SHoward Hinnant{ 6840fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 6853e519524SHoward Hinnant { 6863e519524SHoward Hinnant __call_once_param<_Callable> __p(__func); 6873e519524SHoward Hinnant __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); 6883e519524SHoward Hinnant } 6893e519524SHoward Hinnant} 6903e519524SHoward Hinnant 691793f59e7SEric Fiseliertemplate<class _Callable> 692793f59e7SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 693793f59e7SEric Fiseliervoid 694793f59e7SEric Fiseliercall_once(once_flag& __flag, const _Callable& __func) 695793f59e7SEric Fiselier{ 6960fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 697793f59e7SEric Fiselier { 698793f59e7SEric Fiselier __call_once_param<const _Callable> __p(__func); 699793f59e7SEric Fiselier __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); 700793f59e7SEric Fiselier } 701793f59e7SEric Fiselier} 702793f59e7SEric Fiselier 703e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 7043e519524SHoward Hinnant 7053e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD 7063e519524SHoward Hinnant 707a016efb1SEric Fiselier_LIBCPP_POP_MACROS 708a016efb1SEric Fiselier 7093e519524SHoward Hinnant#endif // _LIBCPP_MUTEX 710