1*4d6fc14bSjoerg// -*- C++ -*- 2*4d6fc14bSjoerg//===--------------------------- mutex ------------------------------------===// 3*4d6fc14bSjoerg// 4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information. 6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4d6fc14bSjoerg// 8*4d6fc14bSjoerg//===----------------------------------------------------------------------===// 9*4d6fc14bSjoerg 10*4d6fc14bSjoerg#ifndef _LIBCPP_MUTEX 11*4d6fc14bSjoerg#define _LIBCPP_MUTEX 12*4d6fc14bSjoerg 13*4d6fc14bSjoerg/* 14*4d6fc14bSjoerg mutex synopsis 15*4d6fc14bSjoerg 16*4d6fc14bSjoergnamespace std 17*4d6fc14bSjoerg{ 18*4d6fc14bSjoerg 19*4d6fc14bSjoergclass mutex 20*4d6fc14bSjoerg{ 21*4d6fc14bSjoergpublic: 22*4d6fc14bSjoerg constexpr mutex() noexcept; 23*4d6fc14bSjoerg ~mutex(); 24*4d6fc14bSjoerg 25*4d6fc14bSjoerg mutex(const mutex&) = delete; 26*4d6fc14bSjoerg mutex& operator=(const mutex&) = delete; 27*4d6fc14bSjoerg 28*4d6fc14bSjoerg void lock(); 29*4d6fc14bSjoerg bool try_lock(); 30*4d6fc14bSjoerg void unlock(); 31*4d6fc14bSjoerg 32*4d6fc14bSjoerg typedef pthread_mutex_t* native_handle_type; 33*4d6fc14bSjoerg native_handle_type native_handle(); 34*4d6fc14bSjoerg}; 35*4d6fc14bSjoerg 36*4d6fc14bSjoergclass recursive_mutex 37*4d6fc14bSjoerg{ 38*4d6fc14bSjoergpublic: 39*4d6fc14bSjoerg recursive_mutex(); 40*4d6fc14bSjoerg ~recursive_mutex(); 41*4d6fc14bSjoerg 42*4d6fc14bSjoerg recursive_mutex(const recursive_mutex&) = delete; 43*4d6fc14bSjoerg recursive_mutex& operator=(const recursive_mutex&) = delete; 44*4d6fc14bSjoerg 45*4d6fc14bSjoerg void lock(); 46*4d6fc14bSjoerg bool try_lock() noexcept; 47*4d6fc14bSjoerg void unlock(); 48*4d6fc14bSjoerg 49*4d6fc14bSjoerg typedef pthread_mutex_t* native_handle_type; 50*4d6fc14bSjoerg native_handle_type native_handle(); 51*4d6fc14bSjoerg}; 52*4d6fc14bSjoerg 53*4d6fc14bSjoergclass timed_mutex 54*4d6fc14bSjoerg{ 55*4d6fc14bSjoergpublic: 56*4d6fc14bSjoerg timed_mutex(); 57*4d6fc14bSjoerg ~timed_mutex(); 58*4d6fc14bSjoerg 59*4d6fc14bSjoerg timed_mutex(const timed_mutex&) = delete; 60*4d6fc14bSjoerg timed_mutex& operator=(const timed_mutex&) = delete; 61*4d6fc14bSjoerg 62*4d6fc14bSjoerg void lock(); 63*4d6fc14bSjoerg bool try_lock(); 64*4d6fc14bSjoerg template <class Rep, class Period> 65*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 66*4d6fc14bSjoerg template <class Clock, class Duration> 67*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 68*4d6fc14bSjoerg void unlock(); 69*4d6fc14bSjoerg}; 70*4d6fc14bSjoerg 71*4d6fc14bSjoergclass recursive_timed_mutex 72*4d6fc14bSjoerg{ 73*4d6fc14bSjoergpublic: 74*4d6fc14bSjoerg recursive_timed_mutex(); 75*4d6fc14bSjoerg ~recursive_timed_mutex(); 76*4d6fc14bSjoerg 77*4d6fc14bSjoerg recursive_timed_mutex(const recursive_timed_mutex&) = delete; 78*4d6fc14bSjoerg recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 79*4d6fc14bSjoerg 80*4d6fc14bSjoerg void lock(); 81*4d6fc14bSjoerg bool try_lock() noexcept; 82*4d6fc14bSjoerg template <class Rep, class Period> 83*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 84*4d6fc14bSjoerg template <class Clock, class Duration> 85*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 86*4d6fc14bSjoerg void unlock(); 87*4d6fc14bSjoerg}; 88*4d6fc14bSjoerg 89*4d6fc14bSjoergstruct defer_lock_t { explicit defer_lock_t() = default; }; 90*4d6fc14bSjoergstruct try_to_lock_t { explicit try_to_lock_t() = default; }; 91*4d6fc14bSjoergstruct adopt_lock_t { explicit adopt_lock_t() = default; }; 92*4d6fc14bSjoerg 93*4d6fc14bSjoerginline constexpr defer_lock_t defer_lock{}; 94*4d6fc14bSjoerginline constexpr try_to_lock_t try_to_lock{}; 95*4d6fc14bSjoerginline constexpr adopt_lock_t adopt_lock{}; 96*4d6fc14bSjoerg 97*4d6fc14bSjoergtemplate <class Mutex> 98*4d6fc14bSjoergclass lock_guard 99*4d6fc14bSjoerg{ 100*4d6fc14bSjoergpublic: 101*4d6fc14bSjoerg typedef Mutex mutex_type; 102*4d6fc14bSjoerg 103*4d6fc14bSjoerg explicit lock_guard(mutex_type& m); 104*4d6fc14bSjoerg lock_guard(mutex_type& m, adopt_lock_t); 105*4d6fc14bSjoerg ~lock_guard(); 106*4d6fc14bSjoerg 107*4d6fc14bSjoerg lock_guard(lock_guard const&) = delete; 108*4d6fc14bSjoerg lock_guard& operator=(lock_guard const&) = delete; 109*4d6fc14bSjoerg}; 110*4d6fc14bSjoerg 111*4d6fc14bSjoergtemplate <class... MutexTypes> 112*4d6fc14bSjoergclass scoped_lock // C++17 113*4d6fc14bSjoerg{ 114*4d6fc14bSjoergpublic: 115*4d6fc14bSjoerg using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex 116*4d6fc14bSjoerg 117*4d6fc14bSjoerg explicit scoped_lock(MutexTypes&... m); 118*4d6fc14bSjoerg scoped_lock(adopt_lock_t, MutexTypes&... m); 119*4d6fc14bSjoerg ~scoped_lock(); 120*4d6fc14bSjoerg scoped_lock(scoped_lock const&) = delete; 121*4d6fc14bSjoerg scoped_lock& operator=(scoped_lock const&) = delete; 122*4d6fc14bSjoergprivate: 123*4d6fc14bSjoerg tuple<MutexTypes&...> pm; // exposition only 124*4d6fc14bSjoerg}; 125*4d6fc14bSjoerg 126*4d6fc14bSjoergtemplate <class Mutex> 127*4d6fc14bSjoergclass unique_lock 128*4d6fc14bSjoerg{ 129*4d6fc14bSjoergpublic: 130*4d6fc14bSjoerg typedef Mutex mutex_type; 131*4d6fc14bSjoerg unique_lock() noexcept; 132*4d6fc14bSjoerg explicit unique_lock(mutex_type& m); 133*4d6fc14bSjoerg unique_lock(mutex_type& m, defer_lock_t) noexcept; 134*4d6fc14bSjoerg unique_lock(mutex_type& m, try_to_lock_t); 135*4d6fc14bSjoerg unique_lock(mutex_type& m, adopt_lock_t); 136*4d6fc14bSjoerg template <class Clock, class Duration> 137*4d6fc14bSjoerg unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); 138*4d6fc14bSjoerg template <class Rep, class Period> 139*4d6fc14bSjoerg unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); 140*4d6fc14bSjoerg ~unique_lock(); 141*4d6fc14bSjoerg 142*4d6fc14bSjoerg unique_lock(unique_lock const&) = delete; 143*4d6fc14bSjoerg unique_lock& operator=(unique_lock const&) = delete; 144*4d6fc14bSjoerg 145*4d6fc14bSjoerg unique_lock(unique_lock&& u) noexcept; 146*4d6fc14bSjoerg unique_lock& operator=(unique_lock&& u) noexcept; 147*4d6fc14bSjoerg 148*4d6fc14bSjoerg void lock(); 149*4d6fc14bSjoerg bool try_lock(); 150*4d6fc14bSjoerg 151*4d6fc14bSjoerg template <class Rep, class Period> 152*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 153*4d6fc14bSjoerg template <class Clock, class Duration> 154*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 155*4d6fc14bSjoerg 156*4d6fc14bSjoerg void unlock(); 157*4d6fc14bSjoerg 158*4d6fc14bSjoerg void swap(unique_lock& u) noexcept; 159*4d6fc14bSjoerg mutex_type* release() noexcept; 160*4d6fc14bSjoerg 161*4d6fc14bSjoerg bool owns_lock() const noexcept; 162*4d6fc14bSjoerg explicit operator bool () const noexcept; 163*4d6fc14bSjoerg mutex_type* mutex() const noexcept; 164*4d6fc14bSjoerg}; 165*4d6fc14bSjoerg 166*4d6fc14bSjoergtemplate <class Mutex> 167*4d6fc14bSjoerg void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; 168*4d6fc14bSjoerg 169*4d6fc14bSjoergtemplate <class L1, class L2, class... L3> 170*4d6fc14bSjoerg int try_lock(L1&, L2&, L3&...); 171*4d6fc14bSjoergtemplate <class L1, class L2, class... L3> 172*4d6fc14bSjoerg void lock(L1&, L2&, L3&...); 173*4d6fc14bSjoerg 174*4d6fc14bSjoergstruct once_flag 175*4d6fc14bSjoerg{ 176*4d6fc14bSjoerg constexpr once_flag() noexcept; 177*4d6fc14bSjoerg 178*4d6fc14bSjoerg once_flag(const once_flag&) = delete; 179*4d6fc14bSjoerg once_flag& operator=(const once_flag&) = delete; 180*4d6fc14bSjoerg}; 181*4d6fc14bSjoerg 182*4d6fc14bSjoergtemplate<class Callable, class ...Args> 183*4d6fc14bSjoerg void call_once(once_flag& flag, Callable&& func, Args&&... args); 184*4d6fc14bSjoerg 185*4d6fc14bSjoerg} // std 186*4d6fc14bSjoerg 187*4d6fc14bSjoerg*/ 188*4d6fc14bSjoerg 189*4d6fc14bSjoerg#include <__config> 190*4d6fc14bSjoerg#include <__mutex_base> 191*4d6fc14bSjoerg#include <cstdint> 192*4d6fc14bSjoerg#include <functional> 193*4d6fc14bSjoerg#include <memory> 194*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 195*4d6fc14bSjoerg#include <tuple> 196*4d6fc14bSjoerg#endif 197*4d6fc14bSjoerg#include <version> 198*4d6fc14bSjoerg#include <__threading_support> 199*4d6fc14bSjoerg 200*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 201*4d6fc14bSjoerg#pragma GCC system_header 202*4d6fc14bSjoerg#endif 203*4d6fc14bSjoerg 204*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS 205*4d6fc14bSjoerg#include <__undef_macros> 206*4d6fc14bSjoerg 207*4d6fc14bSjoerg 208*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD 209*4d6fc14bSjoerg 210*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_THREADS 211*4d6fc14bSjoerg 212*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS recursive_mutex 213*4d6fc14bSjoerg{ 214*4d6fc14bSjoerg __libcpp_recursive_mutex_t __m_; 215*4d6fc14bSjoerg 216*4d6fc14bSjoergpublic: 217*4d6fc14bSjoerg recursive_mutex(); 218*4d6fc14bSjoerg ~recursive_mutex(); 219*4d6fc14bSjoerg 220*4d6fc14bSjoergprivate: 221*4d6fc14bSjoerg recursive_mutex(const recursive_mutex&); // = delete; 222*4d6fc14bSjoerg recursive_mutex& operator=(const recursive_mutex&); // = delete; 223*4d6fc14bSjoerg 224*4d6fc14bSjoergpublic: 225*4d6fc14bSjoerg void lock(); 226*4d6fc14bSjoerg bool try_lock() _NOEXCEPT; 227*4d6fc14bSjoerg void unlock() _NOEXCEPT; 228*4d6fc14bSjoerg 229*4d6fc14bSjoerg typedef __libcpp_recursive_mutex_t* native_handle_type; 230*4d6fc14bSjoerg 231*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 232*4d6fc14bSjoerg native_handle_type native_handle() {return &__m_;} 233*4d6fc14bSjoerg}; 234*4d6fc14bSjoerg 235*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS timed_mutex 236*4d6fc14bSjoerg{ 237*4d6fc14bSjoerg mutex __m_; 238*4d6fc14bSjoerg condition_variable __cv_; 239*4d6fc14bSjoerg bool __locked_; 240*4d6fc14bSjoergpublic: 241*4d6fc14bSjoerg timed_mutex(); 242*4d6fc14bSjoerg ~timed_mutex(); 243*4d6fc14bSjoerg 244*4d6fc14bSjoergprivate: 245*4d6fc14bSjoerg timed_mutex(const timed_mutex&); // = delete; 246*4d6fc14bSjoerg timed_mutex& operator=(const timed_mutex&); // = delete; 247*4d6fc14bSjoerg 248*4d6fc14bSjoergpublic: 249*4d6fc14bSjoerg void lock(); 250*4d6fc14bSjoerg bool try_lock() _NOEXCEPT; 251*4d6fc14bSjoerg template <class _Rep, class _Period> 252*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 253*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 254*4d6fc14bSjoerg {return try_lock_until(chrono::steady_clock::now() + __d);} 255*4d6fc14bSjoerg template <class _Clock, class _Duration> 256*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 257*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 258*4d6fc14bSjoerg void unlock() _NOEXCEPT; 259*4d6fc14bSjoerg}; 260*4d6fc14bSjoerg 261*4d6fc14bSjoergtemplate <class _Clock, class _Duration> 262*4d6fc14bSjoergbool 263*4d6fc14bSjoergtimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 264*4d6fc14bSjoerg{ 265*4d6fc14bSjoerg using namespace chrono; 266*4d6fc14bSjoerg unique_lock<mutex> __lk(__m_); 267*4d6fc14bSjoerg bool no_timeout = _Clock::now() < __t; 268*4d6fc14bSjoerg while (no_timeout && __locked_) 269*4d6fc14bSjoerg no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 270*4d6fc14bSjoerg if (!__locked_) 271*4d6fc14bSjoerg { 272*4d6fc14bSjoerg __locked_ = true; 273*4d6fc14bSjoerg return true; 274*4d6fc14bSjoerg } 275*4d6fc14bSjoerg return false; 276*4d6fc14bSjoerg} 277*4d6fc14bSjoerg 278*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS recursive_timed_mutex 279*4d6fc14bSjoerg{ 280*4d6fc14bSjoerg mutex __m_; 281*4d6fc14bSjoerg condition_variable __cv_; 282*4d6fc14bSjoerg size_t __count_; 283*4d6fc14bSjoerg __thread_id __id_; 284*4d6fc14bSjoergpublic: 285*4d6fc14bSjoerg recursive_timed_mutex(); 286*4d6fc14bSjoerg ~recursive_timed_mutex(); 287*4d6fc14bSjoerg 288*4d6fc14bSjoergprivate: 289*4d6fc14bSjoerg recursive_timed_mutex(const recursive_timed_mutex&); // = delete; 290*4d6fc14bSjoerg recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; 291*4d6fc14bSjoerg 292*4d6fc14bSjoergpublic: 293*4d6fc14bSjoerg void lock(); 294*4d6fc14bSjoerg bool try_lock() _NOEXCEPT; 295*4d6fc14bSjoerg template <class _Rep, class _Period> 296*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 297*4d6fc14bSjoerg bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 298*4d6fc14bSjoerg {return try_lock_until(chrono::steady_clock::now() + __d);} 299*4d6fc14bSjoerg template <class _Clock, class _Duration> 300*4d6fc14bSjoerg _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 301*4d6fc14bSjoerg bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 302*4d6fc14bSjoerg void unlock() _NOEXCEPT; 303*4d6fc14bSjoerg}; 304*4d6fc14bSjoerg 305*4d6fc14bSjoergtemplate <class _Clock, class _Duration> 306*4d6fc14bSjoergbool 307*4d6fc14bSjoergrecursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 308*4d6fc14bSjoerg{ 309*4d6fc14bSjoerg using namespace chrono; 310*4d6fc14bSjoerg __thread_id __id = this_thread::get_id(); 311*4d6fc14bSjoerg unique_lock<mutex> lk(__m_); 312*4d6fc14bSjoerg if (__id == __id_) 313*4d6fc14bSjoerg { 314*4d6fc14bSjoerg if (__count_ == numeric_limits<size_t>::max()) 315*4d6fc14bSjoerg return false; 316*4d6fc14bSjoerg ++__count_; 317*4d6fc14bSjoerg return true; 318*4d6fc14bSjoerg } 319*4d6fc14bSjoerg bool no_timeout = _Clock::now() < __t; 320*4d6fc14bSjoerg while (no_timeout && __count_ != 0) 321*4d6fc14bSjoerg no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; 322*4d6fc14bSjoerg if (__count_ == 0) 323*4d6fc14bSjoerg { 324*4d6fc14bSjoerg __count_ = 1; 325*4d6fc14bSjoerg __id_ = __id; 326*4d6fc14bSjoerg return true; 327*4d6fc14bSjoerg } 328*4d6fc14bSjoerg return false; 329*4d6fc14bSjoerg} 330*4d6fc14bSjoerg 331*4d6fc14bSjoergtemplate <class _L0, class _L1> 332*4d6fc14bSjoergint 333*4d6fc14bSjoergtry_lock(_L0& __l0, _L1& __l1) 334*4d6fc14bSjoerg{ 335*4d6fc14bSjoerg unique_lock<_L0> __u0(__l0, try_to_lock); 336*4d6fc14bSjoerg if (__u0.owns_lock()) 337*4d6fc14bSjoerg { 338*4d6fc14bSjoerg if (__l1.try_lock()) 339*4d6fc14bSjoerg { 340*4d6fc14bSjoerg __u0.release(); 341*4d6fc14bSjoerg return -1; 342*4d6fc14bSjoerg } 343*4d6fc14bSjoerg else 344*4d6fc14bSjoerg return 1; 345*4d6fc14bSjoerg } 346*4d6fc14bSjoerg return 0; 347*4d6fc14bSjoerg} 348*4d6fc14bSjoerg 349*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 350*4d6fc14bSjoerg 351*4d6fc14bSjoergtemplate <class _L0, class _L1, class _L2, class... _L3> 352*4d6fc14bSjoergint 353*4d6fc14bSjoergtry_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) 354*4d6fc14bSjoerg{ 355*4d6fc14bSjoerg int __r = 0; 356*4d6fc14bSjoerg unique_lock<_L0> __u0(__l0, try_to_lock); 357*4d6fc14bSjoerg if (__u0.owns_lock()) 358*4d6fc14bSjoerg { 359*4d6fc14bSjoerg __r = try_lock(__l1, __l2, __l3...); 360*4d6fc14bSjoerg if (__r == -1) 361*4d6fc14bSjoerg __u0.release(); 362*4d6fc14bSjoerg else 363*4d6fc14bSjoerg ++__r; 364*4d6fc14bSjoerg } 365*4d6fc14bSjoerg return __r; 366*4d6fc14bSjoerg} 367*4d6fc14bSjoerg 368*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG 369*4d6fc14bSjoerg 370*4d6fc14bSjoergtemplate <class _L0, class _L1> 371*4d6fc14bSjoergvoid 372*4d6fc14bSjoerglock(_L0& __l0, _L1& __l1) 373*4d6fc14bSjoerg{ 374*4d6fc14bSjoerg while (true) 375*4d6fc14bSjoerg { 376*4d6fc14bSjoerg { 377*4d6fc14bSjoerg unique_lock<_L0> __u0(__l0); 378*4d6fc14bSjoerg if (__l1.try_lock()) 379*4d6fc14bSjoerg { 380*4d6fc14bSjoerg __u0.release(); 381*4d6fc14bSjoerg break; 382*4d6fc14bSjoerg } 383*4d6fc14bSjoerg } 384*4d6fc14bSjoerg __libcpp_thread_yield(); 385*4d6fc14bSjoerg { 386*4d6fc14bSjoerg unique_lock<_L1> __u1(__l1); 387*4d6fc14bSjoerg if (__l0.try_lock()) 388*4d6fc14bSjoerg { 389*4d6fc14bSjoerg __u1.release(); 390*4d6fc14bSjoerg break; 391*4d6fc14bSjoerg } 392*4d6fc14bSjoerg } 393*4d6fc14bSjoerg __libcpp_thread_yield(); 394*4d6fc14bSjoerg } 395*4d6fc14bSjoerg} 396*4d6fc14bSjoerg 397*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 398*4d6fc14bSjoerg 399*4d6fc14bSjoergtemplate <class _L0, class _L1, class _L2, class ..._L3> 400*4d6fc14bSjoergvoid 401*4d6fc14bSjoerg__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 402*4d6fc14bSjoerg{ 403*4d6fc14bSjoerg while (true) 404*4d6fc14bSjoerg { 405*4d6fc14bSjoerg switch (__i) 406*4d6fc14bSjoerg { 407*4d6fc14bSjoerg case 0: 408*4d6fc14bSjoerg { 409*4d6fc14bSjoerg unique_lock<_L0> __u0(__l0); 410*4d6fc14bSjoerg __i = try_lock(__l1, __l2, __l3...); 411*4d6fc14bSjoerg if (__i == -1) 412*4d6fc14bSjoerg { 413*4d6fc14bSjoerg __u0.release(); 414*4d6fc14bSjoerg return; 415*4d6fc14bSjoerg } 416*4d6fc14bSjoerg } 417*4d6fc14bSjoerg ++__i; 418*4d6fc14bSjoerg __libcpp_thread_yield(); 419*4d6fc14bSjoerg break; 420*4d6fc14bSjoerg case 1: 421*4d6fc14bSjoerg { 422*4d6fc14bSjoerg unique_lock<_L1> __u1(__l1); 423*4d6fc14bSjoerg __i = try_lock(__l2, __l3..., __l0); 424*4d6fc14bSjoerg if (__i == -1) 425*4d6fc14bSjoerg { 426*4d6fc14bSjoerg __u1.release(); 427*4d6fc14bSjoerg return; 428*4d6fc14bSjoerg } 429*4d6fc14bSjoerg } 430*4d6fc14bSjoerg if (__i == sizeof...(_L3) + 1) 431*4d6fc14bSjoerg __i = 0; 432*4d6fc14bSjoerg else 433*4d6fc14bSjoerg __i += 2; 434*4d6fc14bSjoerg __libcpp_thread_yield(); 435*4d6fc14bSjoerg break; 436*4d6fc14bSjoerg default: 437*4d6fc14bSjoerg __lock_first(__i - 2, __l2, __l3..., __l0, __l1); 438*4d6fc14bSjoerg return; 439*4d6fc14bSjoerg } 440*4d6fc14bSjoerg } 441*4d6fc14bSjoerg} 442*4d6fc14bSjoerg 443*4d6fc14bSjoergtemplate <class _L0, class _L1, class _L2, class ..._L3> 444*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 445*4d6fc14bSjoergvoid 446*4d6fc14bSjoerglock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 447*4d6fc14bSjoerg{ 448*4d6fc14bSjoerg __lock_first(0, __l0, __l1, __l2, __l3...); 449*4d6fc14bSjoerg} 450*4d6fc14bSjoerg 451*4d6fc14bSjoergtemplate <class _L0> 452*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 453*4d6fc14bSjoergvoid __unlock(_L0& __l0) { 454*4d6fc14bSjoerg __l0.unlock(); 455*4d6fc14bSjoerg} 456*4d6fc14bSjoerg 457*4d6fc14bSjoergtemplate <class _L0, class _L1> 458*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 459*4d6fc14bSjoergvoid __unlock(_L0& __l0, _L1& __l1) { 460*4d6fc14bSjoerg __l0.unlock(); 461*4d6fc14bSjoerg __l1.unlock(); 462*4d6fc14bSjoerg} 463*4d6fc14bSjoerg 464*4d6fc14bSjoergtemplate <class _L0, class _L1, class _L2, class ..._L3> 465*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 466*4d6fc14bSjoergvoid __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 467*4d6fc14bSjoerg __l0.unlock(); 468*4d6fc14bSjoerg __l1.unlock(); 469*4d6fc14bSjoerg _VSTD::__unlock(__l2, __l3...); 470*4d6fc14bSjoerg} 471*4d6fc14bSjoerg 472*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG 473*4d6fc14bSjoerg 474*4d6fc14bSjoerg#if _LIBCPP_STD_VER > 14 475*4d6fc14bSjoergtemplate <class ..._Mutexes> 476*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS scoped_lock; 477*4d6fc14bSjoerg 478*4d6fc14bSjoergtemplate <> 479*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS scoped_lock<> { 480*4d6fc14bSjoergpublic: 481*4d6fc14bSjoerg explicit scoped_lock() {} 482*4d6fc14bSjoerg ~scoped_lock() = default; 483*4d6fc14bSjoerg 484*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 485*4d6fc14bSjoerg explicit scoped_lock(adopt_lock_t) {} 486*4d6fc14bSjoerg 487*4d6fc14bSjoerg scoped_lock(scoped_lock const&) = delete; 488*4d6fc14bSjoerg scoped_lock& operator=(scoped_lock const&) = delete; 489*4d6fc14bSjoerg}; 490*4d6fc14bSjoerg 491*4d6fc14bSjoergtemplate <class _Mutex> 492*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { 493*4d6fc14bSjoergpublic: 494*4d6fc14bSjoerg typedef _Mutex mutex_type; 495*4d6fc14bSjoergprivate: 496*4d6fc14bSjoerg mutex_type& __m_; 497*4d6fc14bSjoergpublic: 498*4d6fc14bSjoerg explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 499*4d6fc14bSjoerg : __m_(__m) {__m_.lock();} 500*4d6fc14bSjoerg 501*4d6fc14bSjoerg ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 502*4d6fc14bSjoerg 503*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 504*4d6fc14bSjoerg explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 505*4d6fc14bSjoerg : __m_(__m) {} 506*4d6fc14bSjoerg 507*4d6fc14bSjoerg scoped_lock(scoped_lock const&) = delete; 508*4d6fc14bSjoerg scoped_lock& operator=(scoped_lock const&) = delete; 509*4d6fc14bSjoerg}; 510*4d6fc14bSjoerg 511*4d6fc14bSjoergtemplate <class ..._MArgs> 512*4d6fc14bSjoergclass _LIBCPP_TEMPLATE_VIS scoped_lock 513*4d6fc14bSjoerg{ 514*4d6fc14bSjoerg static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); 515*4d6fc14bSjoerg typedef tuple<_MArgs&...> _MutexTuple; 516*4d6fc14bSjoerg 517*4d6fc14bSjoergpublic: 518*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 519*4d6fc14bSjoerg explicit scoped_lock(_MArgs&... __margs) 520*4d6fc14bSjoerg : __t_(__margs...) 521*4d6fc14bSjoerg { 522*4d6fc14bSjoerg _VSTD::lock(__margs...); 523*4d6fc14bSjoerg } 524*4d6fc14bSjoerg 525*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 526*4d6fc14bSjoerg scoped_lock(adopt_lock_t, _MArgs&... __margs) 527*4d6fc14bSjoerg : __t_(__margs...) 528*4d6fc14bSjoerg { 529*4d6fc14bSjoerg } 530*4d6fc14bSjoerg 531*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 532*4d6fc14bSjoerg ~scoped_lock() { 533*4d6fc14bSjoerg typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; 534*4d6fc14bSjoerg __unlock_unpack(_Indices{}, __t_); 535*4d6fc14bSjoerg } 536*4d6fc14bSjoerg 537*4d6fc14bSjoerg scoped_lock(scoped_lock const&) = delete; 538*4d6fc14bSjoerg scoped_lock& operator=(scoped_lock const&) = delete; 539*4d6fc14bSjoerg 540*4d6fc14bSjoergprivate: 541*4d6fc14bSjoerg template <size_t ..._Indx> 542*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 543*4d6fc14bSjoerg static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { 544*4d6fc14bSjoerg _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); 545*4d6fc14bSjoerg } 546*4d6fc14bSjoerg 547*4d6fc14bSjoerg _MutexTuple __t_; 548*4d6fc14bSjoerg}; 549*4d6fc14bSjoerg 550*4d6fc14bSjoerg#endif // _LIBCPP_STD_VER > 14 551*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS 552*4d6fc14bSjoerg 553*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS once_flag; 554*4d6fc14bSjoerg 555*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 556*4d6fc14bSjoerg 557*4d6fc14bSjoergtemplate<class _Callable, class... _Args> 558*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY 559*4d6fc14bSjoergvoid call_once(once_flag&, _Callable&&, _Args&&...); 560*4d6fc14bSjoerg 561*4d6fc14bSjoerg#else // _LIBCPP_CXX03_LANG 562*4d6fc14bSjoerg 563*4d6fc14bSjoergtemplate<class _Callable> 564*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY 565*4d6fc14bSjoergvoid call_once(once_flag&, _Callable&); 566*4d6fc14bSjoerg 567*4d6fc14bSjoergtemplate<class _Callable> 568*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY 569*4d6fc14bSjoergvoid call_once(once_flag&, const _Callable&); 570*4d6fc14bSjoerg 571*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG 572*4d6fc14bSjoerg 573*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS once_flag 574*4d6fc14bSjoerg{ 575*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 576*4d6fc14bSjoerg _LIBCPP_CONSTEXPR 577*4d6fc14bSjoerg once_flag() _NOEXCEPT : __state_(0) {} 578*4d6fc14bSjoerg 579*4d6fc14bSjoerg#if defined(_LIBCPP_ABI_MICROSOFT) 580*4d6fc14bSjoerg typedef uintptr_t _State_type; 581*4d6fc14bSjoerg#else 582*4d6fc14bSjoerg typedef unsigned long _State_type; 583*4d6fc14bSjoerg#endif 584*4d6fc14bSjoerg 585*4d6fc14bSjoerg 586*4d6fc14bSjoergprivate: 587*4d6fc14bSjoerg once_flag(const once_flag&); // = delete; 588*4d6fc14bSjoerg once_flag& operator=(const once_flag&); // = delete; 589*4d6fc14bSjoerg 590*4d6fc14bSjoerg _State_type __state_; 591*4d6fc14bSjoerg 592*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 593*4d6fc14bSjoerg template<class _Callable, class... _Args> 594*4d6fc14bSjoerg friend 595*4d6fc14bSjoerg void call_once(once_flag&, _Callable&&, _Args&&...); 596*4d6fc14bSjoerg#else // _LIBCPP_CXX03_LANG 597*4d6fc14bSjoerg template<class _Callable> 598*4d6fc14bSjoerg friend 599*4d6fc14bSjoerg void call_once(once_flag&, _Callable&); 600*4d6fc14bSjoerg 601*4d6fc14bSjoerg template<class _Callable> 602*4d6fc14bSjoerg friend 603*4d6fc14bSjoerg void call_once(once_flag&, const _Callable&); 604*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG 605*4d6fc14bSjoerg}; 606*4d6fc14bSjoerg 607*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 608*4d6fc14bSjoerg 609*4d6fc14bSjoergtemplate <class _Fp> 610*4d6fc14bSjoergclass __call_once_param 611*4d6fc14bSjoerg{ 612*4d6fc14bSjoerg _Fp& __f_; 613*4d6fc14bSjoergpublic: 614*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 615*4d6fc14bSjoerg explicit __call_once_param(_Fp& __f) : __f_(__f) {} 616*4d6fc14bSjoerg 617*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 618*4d6fc14bSjoerg void operator()() 619*4d6fc14bSjoerg { 620*4d6fc14bSjoerg typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 621*4d6fc14bSjoerg __execute(_Index()); 622*4d6fc14bSjoerg } 623*4d6fc14bSjoerg 624*4d6fc14bSjoergprivate: 625*4d6fc14bSjoerg template <size_t ..._Indices> 626*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 627*4d6fc14bSjoerg void __execute(__tuple_indices<_Indices...>) 628*4d6fc14bSjoerg { 629*4d6fc14bSjoerg _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); 630*4d6fc14bSjoerg } 631*4d6fc14bSjoerg}; 632*4d6fc14bSjoerg 633*4d6fc14bSjoerg#else 634*4d6fc14bSjoerg 635*4d6fc14bSjoergtemplate <class _Fp> 636*4d6fc14bSjoergclass __call_once_param 637*4d6fc14bSjoerg{ 638*4d6fc14bSjoerg _Fp& __f_; 639*4d6fc14bSjoergpublic: 640*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 641*4d6fc14bSjoerg explicit __call_once_param(_Fp& __f) : __f_(__f) {} 642*4d6fc14bSjoerg 643*4d6fc14bSjoerg _LIBCPP_INLINE_VISIBILITY 644*4d6fc14bSjoerg void operator()() 645*4d6fc14bSjoerg { 646*4d6fc14bSjoerg __f_(); 647*4d6fc14bSjoerg } 648*4d6fc14bSjoerg}; 649*4d6fc14bSjoerg 650*4d6fc14bSjoerg#endif 651*4d6fc14bSjoerg 652*4d6fc14bSjoergtemplate <class _Fp> 653*4d6fc14bSjoergvoid _LIBCPP_INLINE_VISIBILITY 654*4d6fc14bSjoerg__call_once_proxy(void* __vp) 655*4d6fc14bSjoerg{ 656*4d6fc14bSjoerg __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); 657*4d6fc14bSjoerg (*__p)(); 658*4d6fc14bSjoerg} 659*4d6fc14bSjoerg 660*4d6fc14bSjoerg_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, 661*4d6fc14bSjoerg void (*)(void*)); 662*4d6fc14bSjoerg 663*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG 664*4d6fc14bSjoerg 665*4d6fc14bSjoergtemplate<class _Callable, class... _Args> 666*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 667*4d6fc14bSjoergvoid 668*4d6fc14bSjoergcall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) 669*4d6fc14bSjoerg{ 670*4d6fc14bSjoerg if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 671*4d6fc14bSjoerg { 672*4d6fc14bSjoerg typedef tuple<_Callable&&, _Args&&...> _Gp; 673*4d6fc14bSjoerg _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); 674*4d6fc14bSjoerg __call_once_param<_Gp> __p(__f); 675*4d6fc14bSjoerg __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); 676*4d6fc14bSjoerg } 677*4d6fc14bSjoerg} 678*4d6fc14bSjoerg 679*4d6fc14bSjoerg#else // _LIBCPP_CXX03_LANG 680*4d6fc14bSjoerg 681*4d6fc14bSjoergtemplate<class _Callable> 682*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 683*4d6fc14bSjoergvoid 684*4d6fc14bSjoergcall_once(once_flag& __flag, _Callable& __func) 685*4d6fc14bSjoerg{ 686*4d6fc14bSjoerg if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 687*4d6fc14bSjoerg { 688*4d6fc14bSjoerg __call_once_param<_Callable> __p(__func); 689*4d6fc14bSjoerg __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); 690*4d6fc14bSjoerg } 691*4d6fc14bSjoerg} 692*4d6fc14bSjoerg 693*4d6fc14bSjoergtemplate<class _Callable> 694*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY 695*4d6fc14bSjoergvoid 696*4d6fc14bSjoergcall_once(once_flag& __flag, const _Callable& __func) 697*4d6fc14bSjoerg{ 698*4d6fc14bSjoerg if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0)) 699*4d6fc14bSjoerg { 700*4d6fc14bSjoerg __call_once_param<const _Callable> __p(__func); 701*4d6fc14bSjoerg __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); 702*4d6fc14bSjoerg } 703*4d6fc14bSjoerg} 704*4d6fc14bSjoerg 705*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG 706*4d6fc14bSjoerg 707*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD 708*4d6fc14bSjoerg 709*4d6fc14bSjoerg_LIBCPP_POP_MACROS 710*4d6fc14bSjoerg 711*4d6fc14bSjoerg#endif // _LIBCPP_MUTEX 712