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