13e519524SHoward Hinnant// -*- C++ -*- 23e519524SHoward Hinnant//===--------------------------- mutex ------------------------------------===// 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 893e519524SHoward Hinnantstruct defer_lock_t {}; 903e519524SHoward Hinnantstruct try_to_lock_t {}; 913e519524SHoward Hinnantstruct adopt_lock_t {}; 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: 1156015dd11SMarshall Clow using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex 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 1893e519524SHoward Hinnant#include <__config> 1903e519524SHoward Hinnant#include <__mutex_base> 191*0fd00a58SNico Weber#include <cstdint> 1923e519524SHoward Hinnant#include <functional> 1931faf289eSEric Fiselier#include <memory> 194e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 195872a9116SHoward Hinnant#include <tuple> 196872a9116SHoward Hinnant#endif 197f56972e2SMarshall Clow#include <version> 198c7e4239fSAsiri Rathnayake#include <__threading_support> 1993e519524SHoward Hinnant 200073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2013e519524SHoward Hinnant#pragma GCC system_header 202073458b1SHoward Hinnant#endif 2033e519524SHoward Hinnant 204a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS 205a016efb1SEric Fiselier#include <__undef_macros> 206a016efb1SEric Fiselier 207a016efb1SEric Fiselier 2083e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD 2093e519524SHoward Hinnant 210b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS 211b3fcc67fSJonathan Roelofs 2126e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_mutex 2133e519524SHoward Hinnant{ 21458a0dceeSSaleem Abdulrasool __libcpp_recursive_mutex_t __m_; 2153e519524SHoward Hinnant 2163e519524SHoward Hinnantpublic: 2173e519524SHoward Hinnant recursive_mutex(); 2183e519524SHoward Hinnant ~recursive_mutex(); 2193e519524SHoward Hinnant 2203e519524SHoward Hinnantprivate: 2213e519524SHoward Hinnant recursive_mutex(const recursive_mutex&); // = delete; 2223e519524SHoward Hinnant recursive_mutex& operator=(const recursive_mutex&); // = delete; 2233e519524SHoward Hinnant 2243e519524SHoward Hinnantpublic: 2253e519524SHoward Hinnant void lock(); 22602e610efSHoward Hinnant bool try_lock() _NOEXCEPT; 22702e610efSHoward Hinnant void unlock() _NOEXCEPT; 2283e519524SHoward Hinnant 22958a0dceeSSaleem Abdulrasool typedef __libcpp_recursive_mutex_t* native_handle_type; 23058a0dceeSSaleem Abdulrasool 231392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2323e519524SHoward Hinnant native_handle_type native_handle() {return &__m_;} 2333e519524SHoward Hinnant}; 2343e519524SHoward Hinnant 2356e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS timed_mutex 2363e519524SHoward Hinnant{ 2373e519524SHoward Hinnant mutex __m_; 2383e519524SHoward Hinnant condition_variable __cv_; 2393e519524SHoward Hinnant bool __locked_; 2403e519524SHoward Hinnantpublic: 2413e519524SHoward Hinnant timed_mutex(); 2423e519524SHoward Hinnant ~timed_mutex(); 2433e519524SHoward Hinnant 2443e519524SHoward Hinnantprivate: 2453e519524SHoward Hinnant timed_mutex(const timed_mutex&); // = delete; 2463e519524SHoward Hinnant timed_mutex& operator=(const timed_mutex&); // = delete; 2473e519524SHoward Hinnant 2483e519524SHoward Hinnantpublic: 2493e519524SHoward Hinnant void lock(); 25002e610efSHoward Hinnant bool try_lock() _NOEXCEPT; 2513e519524SHoward Hinnant template <class _Rep, class _Period> 252392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 2533e519524SHoward Hinnant bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2543dc6455fSHoward Hinnant {return try_lock_until(chrono::steady_clock::now() + __d);} 2553e519524SHoward Hinnant template <class _Clock, class _Duration> 256bda3c7dfSShoaib Meenai _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2573e519524SHoward Hinnant bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 25802e610efSHoward Hinnant void unlock() _NOEXCEPT; 2593e519524SHoward Hinnant}; 2603e519524SHoward Hinnant 2613e519524SHoward Hinnanttemplate <class _Clock, class _Duration> 2623e519524SHoward Hinnantbool 2633e519524SHoward Hinnanttimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 2643e519524SHoward Hinnant{ 2653e519524SHoward Hinnant using namespace chrono; 2663e519524SHoward Hinnant unique_lock<mutex> __lk(__m_); 2673e519524SHoward Hinnant bool no_timeout = _Clock::now() < __t; 2683e519524SHoward Hinnant while (no_timeout && __locked_) 2693e519524SHoward Hinnant no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 2703e519524SHoward Hinnant if (!__locked_) 2713e519524SHoward Hinnant { 2723e519524SHoward Hinnant __locked_ = true; 2733e519524SHoward Hinnant return true; 2743e519524SHoward Hinnant } 2753e519524SHoward Hinnant return false; 2763e519524SHoward Hinnant} 2773e519524SHoward Hinnant 2786e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_timed_mutex 2793e519524SHoward Hinnant{ 2803e519524SHoward Hinnant mutex __m_; 2813e519524SHoward Hinnant condition_variable __cv_; 2823e519524SHoward Hinnant size_t __count_; 283c7e4239fSAsiri Rathnayake __libcpp_thread_id __id_; 2843e519524SHoward Hinnantpublic: 2853e519524SHoward Hinnant recursive_timed_mutex(); 2863e519524SHoward Hinnant ~recursive_timed_mutex(); 2873e519524SHoward Hinnant 2883e519524SHoward Hinnantprivate: 2893e519524SHoward Hinnant recursive_timed_mutex(const recursive_timed_mutex&); // = delete; 2903e519524SHoward Hinnant recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; 2913e519524SHoward Hinnant 2923e519524SHoward Hinnantpublic: 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; 310c7e4239fSAsiri Rathnayake __libcpp_thread_id __id = __libcpp_thread_get_current_id(); 3113e519524SHoward Hinnant unique_lock<mutex> lk(__m_); 312c7e4239fSAsiri Rathnayake if (__libcpp_thread_id_equal(__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) {} 5783e519524SHoward Hinnant 579*0fd00a58SNico Weber#if defined(_LIBCPP_ABI_MICROSOFT) 580*0fd00a58SNico Weber typedef uintptr_t _State_type; 581*0fd00a58SNico Weber#else 582*0fd00a58SNico Weber typedef unsigned long _State_type; 583*0fd00a58SNico Weber#endif 584*0fd00a58SNico Weber 585*0fd00a58SNico Weber 5863e519524SHoward Hinnantprivate: 5873e519524SHoward Hinnant once_flag(const once_flag&); // = delete; 5883e519524SHoward Hinnant once_flag& operator=(const once_flag&); // = delete; 5893e519524SHoward Hinnant 590*0fd00a58SNico Weber _State_type __state_; 5913e519524SHoward Hinnant 592e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 5933e519524SHoward Hinnant template<class _Callable, class... _Args> 5943e519524SHoward Hinnant friend 5953e519524SHoward Hinnant void call_once(once_flag&, _Callable&&, _Args&&...); 596e11fb13bSEric Fiselier#else // _LIBCPP_CXX03_LANG 5973e519524SHoward Hinnant template<class _Callable> 5983e519524SHoward Hinnant friend 599793f59e7SEric Fiselier void call_once(once_flag&, _Callable&); 600793f59e7SEric Fiselier 601793f59e7SEric Fiselier template<class _Callable> 602793f59e7SEric Fiselier friend 603793f59e7SEric Fiselier void call_once(once_flag&, const _Callable&); 604e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 6053e519524SHoward Hinnant}; 6063e519524SHoward Hinnant 607e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 608872a9116SHoward Hinnant 609c003db1fSHoward Hinnanttemplate <class _Fp> 610872a9116SHoward Hinnantclass __call_once_param 611872a9116SHoward Hinnant{ 612793f59e7SEric Fiselier _Fp& __f_; 613872a9116SHoward Hinnantpublic: 614872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 615793f59e7SEric Fiselier explicit __call_once_param(_Fp& __f) : __f_(__f) {} 616872a9116SHoward Hinnant 617872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 618872a9116SHoward Hinnant void operator()() 619872a9116SHoward Hinnant { 620c003db1fSHoward Hinnant typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 621872a9116SHoward Hinnant __execute(_Index()); 622872a9116SHoward Hinnant } 623872a9116SHoward Hinnant 624872a9116SHoward Hinnantprivate: 625872a9116SHoward Hinnant template <size_t ..._Indices> 626872a9116SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 627872a9116SHoward Hinnant void __execute(__tuple_indices<_Indices...>) 628872a9116SHoward Hinnant { 629793f59e7SEric Fiselier __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); 630872a9116SHoward Hinnant } 631872a9116SHoward Hinnant}; 632872a9116SHoward Hinnant 633872a9116SHoward Hinnant#else 634872a9116SHoward Hinnant 635c003db1fSHoward Hinnanttemplate <class _Fp> 6363e519524SHoward Hinnantclass __call_once_param 6373e519524SHoward Hinnant{ 638793f59e7SEric Fiselier _Fp& __f_; 6393e519524SHoward Hinnantpublic: 640392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 641793f59e7SEric Fiselier explicit __call_once_param(_Fp& __f) : __f_(__f) {} 6423e519524SHoward Hinnant 643392183f9SHoward Hinnant _LIBCPP_INLINE_VISIBILITY 6443e519524SHoward Hinnant void operator()() 6453e519524SHoward Hinnant { 6463e519524SHoward Hinnant __f_(); 6473e519524SHoward Hinnant } 6483e519524SHoward Hinnant}; 6493e519524SHoward Hinnant 650872a9116SHoward Hinnant#endif 651872a9116SHoward Hinnant 652c003db1fSHoward Hinnanttemplate <class _Fp> 6533e519524SHoward Hinnantvoid 6543e519524SHoward Hinnant__call_once_proxy(void* __vp) 6553e519524SHoward Hinnant{ 656c003db1fSHoward Hinnant __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); 6573e519524SHoward Hinnant (*__p)(); 6583e519524SHoward Hinnant} 6593e519524SHoward Hinnant 660*0fd00a58SNico Weber_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, 661*0fd00a58SNico Weber void (*)(void*)); 6623e519524SHoward Hinnant 663e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG 6643e519524SHoward Hinnant 6653e519524SHoward Hinnanttemplate<class _Callable, class... _Args> 6663e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 6673e519524SHoward Hinnantvoid 6683e519524SHoward Hinnantcall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) 6693e519524SHoward Hinnant{ 670*0fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 6713e519524SHoward Hinnant { 672793f59e7SEric Fiselier typedef tuple<_Callable&&, _Args&&...> _Gp; 673793f59e7SEric Fiselier _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); 674793f59e7SEric Fiselier __call_once_param<_Gp> __p(__f); 675c003db1fSHoward Hinnant __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); 6763e519524SHoward Hinnant } 6773e519524SHoward Hinnant} 6783e519524SHoward Hinnant 679e11fb13bSEric Fiselier#else // _LIBCPP_CXX03_LANG 6803e519524SHoward Hinnant 6813e519524SHoward Hinnanttemplate<class _Callable> 6823e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY 6833e519524SHoward Hinnantvoid 684793f59e7SEric Fiseliercall_once(once_flag& __flag, _Callable& __func) 6853e519524SHoward Hinnant{ 686*0fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 6873e519524SHoward Hinnant { 6883e519524SHoward Hinnant __call_once_param<_Callable> __p(__func); 6893e519524SHoward Hinnant __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); 6903e519524SHoward Hinnant } 6913e519524SHoward Hinnant} 6923e519524SHoward Hinnant 693793f59e7SEric Fiseliertemplate<class _Callable> 694793f59e7SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 695793f59e7SEric Fiseliervoid 696793f59e7SEric Fiseliercall_once(once_flag& __flag, const _Callable& __func) 697793f59e7SEric Fiselier{ 698*0fd00a58SNico Weber if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 699793f59e7SEric Fiselier { 700793f59e7SEric Fiselier __call_once_param<const _Callable> __p(__func); 701793f59e7SEric Fiselier __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); 702793f59e7SEric Fiselier } 703793f59e7SEric Fiselier} 704793f59e7SEric Fiselier 705e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG 7063e519524SHoward Hinnant 7073e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD 7083e519524SHoward Hinnant 709a016efb1SEric Fiselier_LIBCPP_POP_MACROS 710a016efb1SEric Fiselier 7113e519524SHoward Hinnant#endif // _LIBCPP_MUTEX 712