17a984708SDavid Chisnall// -*- C++ -*- 27a984708SDavid Chisnall//===--------------------------- mutex ------------------------------------===// 37a984708SDavid Chisnall// 47a984708SDavid Chisnall// The LLVM Compiler Infrastructure 57a984708SDavid Chisnall// 67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open 77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details. 87a984708SDavid Chisnall// 97a984708SDavid Chisnall//===----------------------------------------------------------------------===// 107a984708SDavid Chisnall 117a984708SDavid Chisnall#ifndef _LIBCPP_MUTEX 127a984708SDavid Chisnall#define _LIBCPP_MUTEX 137a984708SDavid Chisnall 147a984708SDavid Chisnall/* 157a984708SDavid Chisnall mutex synopsis 167a984708SDavid Chisnall 177a984708SDavid Chisnallnamespace std 187a984708SDavid Chisnall{ 197a984708SDavid Chisnall 207a984708SDavid Chisnallclass mutex 217a984708SDavid Chisnall{ 227a984708SDavid Chisnallpublic: 23936e9439SDimitry Andric constexpr mutex() noexcept; 247a984708SDavid Chisnall ~mutex(); 257a984708SDavid Chisnall 267a984708SDavid Chisnall mutex(const mutex&) = delete; 277a984708SDavid Chisnall mutex& operator=(const mutex&) = delete; 287a984708SDavid Chisnall 297a984708SDavid Chisnall void lock(); 307a984708SDavid Chisnall bool try_lock(); 317a984708SDavid Chisnall void unlock(); 327a984708SDavid Chisnall 337a984708SDavid Chisnall typedef pthread_mutex_t* native_handle_type; 347a984708SDavid Chisnall native_handle_type native_handle(); 357a984708SDavid Chisnall}; 367a984708SDavid Chisnall 377a984708SDavid Chisnallclass recursive_mutex 387a984708SDavid Chisnall{ 397a984708SDavid Chisnallpublic: 407a984708SDavid Chisnall recursive_mutex(); 417a984708SDavid Chisnall ~recursive_mutex(); 427a984708SDavid Chisnall 437a984708SDavid Chisnall recursive_mutex(const recursive_mutex&) = delete; 447a984708SDavid Chisnall recursive_mutex& operator=(const recursive_mutex&) = delete; 457a984708SDavid Chisnall 467a984708SDavid Chisnall void lock(); 47936e9439SDimitry Andric bool try_lock() noexcept; 487a984708SDavid Chisnall void unlock(); 497a984708SDavid Chisnall 507a984708SDavid Chisnall typedef pthread_mutex_t* native_handle_type; 517a984708SDavid Chisnall native_handle_type native_handle(); 527a984708SDavid Chisnall}; 537a984708SDavid Chisnall 547a984708SDavid Chisnallclass timed_mutex 557a984708SDavid Chisnall{ 567a984708SDavid Chisnallpublic: 577a984708SDavid Chisnall timed_mutex(); 587a984708SDavid Chisnall ~timed_mutex(); 597a984708SDavid Chisnall 607a984708SDavid Chisnall timed_mutex(const timed_mutex&) = delete; 617a984708SDavid Chisnall timed_mutex& operator=(const timed_mutex&) = delete; 627a984708SDavid Chisnall 637a984708SDavid Chisnall void lock(); 647a984708SDavid Chisnall bool try_lock(); 657a984708SDavid Chisnall template <class Rep, class Period> 667a984708SDavid Chisnall bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 677a984708SDavid Chisnall template <class Clock, class Duration> 687a984708SDavid Chisnall bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 697a984708SDavid Chisnall void unlock(); 707a984708SDavid Chisnall}; 717a984708SDavid Chisnall 727a984708SDavid Chisnallclass recursive_timed_mutex 737a984708SDavid Chisnall{ 747a984708SDavid Chisnallpublic: 757a984708SDavid Chisnall recursive_timed_mutex(); 767a984708SDavid Chisnall ~recursive_timed_mutex(); 777a984708SDavid Chisnall 787a984708SDavid Chisnall recursive_timed_mutex(const recursive_timed_mutex&) = delete; 797a984708SDavid Chisnall recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 807a984708SDavid Chisnall 817a984708SDavid Chisnall void lock(); 82936e9439SDimitry Andric bool try_lock() noexcept; 837a984708SDavid Chisnall template <class Rep, class Period> 847a984708SDavid Chisnall bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 857a984708SDavid Chisnall template <class Clock, class Duration> 867a984708SDavid Chisnall bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 877a984708SDavid Chisnall void unlock(); 887a984708SDavid Chisnall}; 897a984708SDavid Chisnall 907a984708SDavid Chisnallstruct defer_lock_t {}; 917a984708SDavid Chisnallstruct try_to_lock_t {}; 927a984708SDavid Chisnallstruct adopt_lock_t {}; 937a984708SDavid Chisnall 9430785c0eSDimitry Andricinline constexpr defer_lock_t defer_lock{}; 9530785c0eSDimitry Andricinline constexpr try_to_lock_t try_to_lock{}; 9630785c0eSDimitry Andricinline constexpr adopt_lock_t adopt_lock{}; 977a984708SDavid Chisnall 987a984708SDavid Chisnalltemplate <class Mutex> 997a984708SDavid Chisnallclass lock_guard 1007a984708SDavid Chisnall{ 1017a984708SDavid Chisnallpublic: 1027a984708SDavid Chisnall typedef Mutex mutex_type; 1037a984708SDavid Chisnall 1047a984708SDavid Chisnall explicit lock_guard(mutex_type& m); 1057a984708SDavid Chisnall lock_guard(mutex_type& m, adopt_lock_t); 1067a984708SDavid Chisnall ~lock_guard(); 1077a984708SDavid Chisnall 1087a984708SDavid Chisnall lock_guard(lock_guard const&) = delete; 1097a984708SDavid Chisnall lock_guard& operator=(lock_guard const&) = delete; 1107a984708SDavid Chisnall}; 1117a984708SDavid Chisnall 112540d2a8bSDimitry Andrictemplate <class... MutexTypes> 113540d2a8bSDimitry Andricclass scoped_lock // C++17 1147c82a1ecSDimitry Andric{ 1157c82a1ecSDimitry Andricpublic: 116540d2a8bSDimitry Andric using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex 117540d2a8bSDimitry Andric 118540d2a8bSDimitry Andric explicit scoped_lock(MutexTypes&... m); 1199dc417c3SDimitry Andric scoped_lock(adopt_lock_t, MutexTypes&... m); 120540d2a8bSDimitry Andric ~scoped_lock(); 121540d2a8bSDimitry Andric scoped_lock(scoped_lock const&) = delete; 122540d2a8bSDimitry Andric scoped_lock& operator=(scoped_lock const&) = delete; 1237c82a1ecSDimitry Andricprivate: 1247c82a1ecSDimitry Andric tuple<MutexTypes&...> pm; // exposition only 1257c82a1ecSDimitry Andric}; 1267c82a1ecSDimitry Andric 1277a984708SDavid Chisnalltemplate <class Mutex> 1287a984708SDavid Chisnallclass unique_lock 1297a984708SDavid Chisnall{ 1307a984708SDavid Chisnallpublic: 1317a984708SDavid Chisnall typedef Mutex mutex_type; 132936e9439SDimitry Andric unique_lock() noexcept; 1337a984708SDavid Chisnall explicit unique_lock(mutex_type& m); 134936e9439SDimitry Andric unique_lock(mutex_type& m, defer_lock_t) noexcept; 1357a984708SDavid Chisnall unique_lock(mutex_type& m, try_to_lock_t); 1367a984708SDavid Chisnall unique_lock(mutex_type& m, adopt_lock_t); 1377a984708SDavid Chisnall template <class Clock, class Duration> 1387a984708SDavid Chisnall unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); 1397a984708SDavid Chisnall template <class Rep, class Period> 1407a984708SDavid Chisnall unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); 1417a984708SDavid Chisnall ~unique_lock(); 1427a984708SDavid Chisnall 1437a984708SDavid Chisnall unique_lock(unique_lock const&) = delete; 1447a984708SDavid Chisnall unique_lock& operator=(unique_lock const&) = delete; 1457a984708SDavid Chisnall 146936e9439SDimitry Andric unique_lock(unique_lock&& u) noexcept; 147936e9439SDimitry Andric unique_lock& operator=(unique_lock&& u) noexcept; 1487a984708SDavid Chisnall 1497a984708SDavid Chisnall void lock(); 1507a984708SDavid Chisnall bool try_lock(); 1517a984708SDavid Chisnall 1527a984708SDavid Chisnall template <class Rep, class Period> 1537a984708SDavid Chisnall bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); 1547a984708SDavid Chisnall template <class Clock, class Duration> 1557a984708SDavid Chisnall bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); 1567a984708SDavid Chisnall 1577a984708SDavid Chisnall void unlock(); 1587a984708SDavid Chisnall 159936e9439SDimitry Andric void swap(unique_lock& u) noexcept; 160936e9439SDimitry Andric mutex_type* release() noexcept; 1617a984708SDavid Chisnall 162936e9439SDimitry Andric bool owns_lock() const noexcept; 163936e9439SDimitry Andric explicit operator bool () const noexcept; 164936e9439SDimitry Andric mutex_type* mutex() const noexcept; 1657a984708SDavid Chisnall}; 1667a984708SDavid Chisnall 1677a984708SDavid Chisnalltemplate <class Mutex> 168936e9439SDimitry Andric void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; 1697a984708SDavid Chisnall 1707a984708SDavid Chisnalltemplate <class L1, class L2, class... L3> 1717a984708SDavid Chisnall int try_lock(L1&, L2&, L3&...); 1727a984708SDavid Chisnalltemplate <class L1, class L2, class... L3> 1737a984708SDavid Chisnall void lock(L1&, L2&, L3&...); 1747a984708SDavid Chisnall 1757a984708SDavid Chisnallstruct once_flag 1767a984708SDavid Chisnall{ 177936e9439SDimitry Andric constexpr once_flag() noexcept; 1787a984708SDavid Chisnall 1797a984708SDavid Chisnall once_flag(const once_flag&) = delete; 1807a984708SDavid Chisnall once_flag& operator=(const once_flag&) = delete; 1817a984708SDavid Chisnall}; 1827a984708SDavid Chisnall 1837a984708SDavid Chisnalltemplate<class Callable, class ...Args> 1847a984708SDavid Chisnall void call_once(once_flag& flag, Callable&& func, Args&&... args); 1857a984708SDavid Chisnall 1867a984708SDavid Chisnall} // std 1877a984708SDavid Chisnall 1887a984708SDavid Chisnall*/ 1897a984708SDavid Chisnall 1907a984708SDavid Chisnall#include <__config> 1917a984708SDavid Chisnall#include <__mutex_base> 1927a984708SDavid Chisnall#include <functional> 193854fa44bSDimitry Andric#include <memory> 194540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 1957a984708SDavid Chisnall#include <tuple> 1967a984708SDavid Chisnall#endif 197b5893f02SDimitry Andric#include <version> 1987c82a1ecSDimitry Andric#include <__threading_support> 1997a984708SDavid Chisnall 2007a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2017a984708SDavid Chisnall#pragma GCC system_header 2027a984708SDavid Chisnall#endif 2037a984708SDavid Chisnall 204f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS 205f9448bf3SDimitry Andric#include <__undef_macros> 206f9448bf3SDimitry Andric 207f9448bf3SDimitry Andric 2087a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD 2097a984708SDavid Chisnall 210d72607e9SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS 211d72607e9SDimitry Andric 2121bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS recursive_mutex 2137a984708SDavid Chisnall{ 214aed8d94eSDimitry Andric __libcpp_recursive_mutex_t __m_; 2157a984708SDavid Chisnall 2167a984708SDavid Chisnallpublic: 2177a984708SDavid Chisnall recursive_mutex(); 2187a984708SDavid Chisnall ~recursive_mutex(); 2197a984708SDavid Chisnall 2207a984708SDavid Chisnallprivate: 2217a984708SDavid Chisnall recursive_mutex(const recursive_mutex&); // = delete; 2227a984708SDavid Chisnall recursive_mutex& operator=(const recursive_mutex&); // = delete; 2237a984708SDavid Chisnall 2247a984708SDavid Chisnallpublic: 2257a984708SDavid Chisnall void lock(); 226936e9439SDimitry Andric bool try_lock() _NOEXCEPT; 227936e9439SDimitry Andric void unlock() _NOEXCEPT; 2287a984708SDavid Chisnall 229aed8d94eSDimitry Andric typedef __libcpp_recursive_mutex_t* native_handle_type; 230aed8d94eSDimitry Andric 2317a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 2327a984708SDavid Chisnall native_handle_type native_handle() {return &__m_;} 2337a984708SDavid Chisnall}; 2347a984708SDavid Chisnall 2351bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS timed_mutex 2367a984708SDavid Chisnall{ 2377a984708SDavid Chisnall mutex __m_; 2387a984708SDavid Chisnall condition_variable __cv_; 2397a984708SDavid Chisnall bool __locked_; 2407a984708SDavid Chisnallpublic: 2417a984708SDavid Chisnall timed_mutex(); 2427a984708SDavid Chisnall ~timed_mutex(); 2437a984708SDavid Chisnall 2447a984708SDavid Chisnallprivate: 2457a984708SDavid Chisnall timed_mutex(const timed_mutex&); // = delete; 2467a984708SDavid Chisnall timed_mutex& operator=(const timed_mutex&); // = delete; 2477a984708SDavid Chisnall 2487a984708SDavid Chisnallpublic: 2497a984708SDavid Chisnall void lock(); 250936e9439SDimitry Andric bool try_lock() _NOEXCEPT; 2517a984708SDavid Chisnall template <class _Rep, class _Period> 2527a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 2537a984708SDavid Chisnall bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2547a984708SDavid Chisnall {return try_lock_until(chrono::steady_clock::now() + __d);} 2557a984708SDavid Chisnall template <class _Clock, class _Duration> 256540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2577a984708SDavid Chisnall bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 258936e9439SDimitry Andric void unlock() _NOEXCEPT; 2597a984708SDavid Chisnall}; 2607a984708SDavid Chisnall 2617a984708SDavid Chisnalltemplate <class _Clock, class _Duration> 2627a984708SDavid Chisnallbool 2637a984708SDavid Chisnalltimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 2647a984708SDavid Chisnall{ 2657a984708SDavid Chisnall using namespace chrono; 2667a984708SDavid Chisnall unique_lock<mutex> __lk(__m_); 2677a984708SDavid Chisnall bool no_timeout = _Clock::now() < __t; 2687a984708SDavid Chisnall while (no_timeout && __locked_) 2697a984708SDavid Chisnall no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; 2707a984708SDavid Chisnall if (!__locked_) 2717a984708SDavid Chisnall { 2727a984708SDavid Chisnall __locked_ = true; 2737a984708SDavid Chisnall return true; 2747a984708SDavid Chisnall } 2757a984708SDavid Chisnall return false; 2767a984708SDavid Chisnall} 2777a984708SDavid Chisnall 2781bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS recursive_timed_mutex 2797a984708SDavid Chisnall{ 2807a984708SDavid Chisnall mutex __m_; 2817a984708SDavid Chisnall condition_variable __cv_; 2827a984708SDavid Chisnall size_t __count_; 283*4173b67fSDimitry Andric __thread_id __id_; 2847a984708SDavid Chisnallpublic: 2857a984708SDavid Chisnall recursive_timed_mutex(); 2867a984708SDavid Chisnall ~recursive_timed_mutex(); 2877a984708SDavid Chisnall 2887a984708SDavid Chisnallprivate: 2897a984708SDavid Chisnall recursive_timed_mutex(const recursive_timed_mutex&); // = delete; 2907a984708SDavid Chisnall recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; 2917a984708SDavid Chisnall 2927a984708SDavid Chisnallpublic: 2937a984708SDavid Chisnall void lock(); 294936e9439SDimitry Andric bool try_lock() _NOEXCEPT; 2957a984708SDavid Chisnall template <class _Rep, class _Period> 2967a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 2977a984708SDavid Chisnall bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) 2987a984708SDavid Chisnall {return try_lock_until(chrono::steady_clock::now() + __d);} 2997a984708SDavid Chisnall template <class _Clock, class _Duration> 300540d2a8bSDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 3017a984708SDavid Chisnall bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 302936e9439SDimitry Andric void unlock() _NOEXCEPT; 3037a984708SDavid Chisnall}; 3047a984708SDavid Chisnall 3057a984708SDavid Chisnalltemplate <class _Clock, class _Duration> 3067a984708SDavid Chisnallbool 3077a984708SDavid Chisnallrecursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 3087a984708SDavid Chisnall{ 3097a984708SDavid Chisnall using namespace chrono; 310*4173b67fSDimitry Andric __thread_id __id = this_thread::get_id(); 3117a984708SDavid Chisnall unique_lock<mutex> lk(__m_); 312*4173b67fSDimitry Andric if (__id == __id_) 3137a984708SDavid Chisnall { 3147a984708SDavid Chisnall if (__count_ == numeric_limits<size_t>::max()) 3157a984708SDavid Chisnall return false; 3167a984708SDavid Chisnall ++__count_; 3177a984708SDavid Chisnall return true; 3187a984708SDavid Chisnall } 3197a984708SDavid Chisnall bool no_timeout = _Clock::now() < __t; 3207a984708SDavid Chisnall while (no_timeout && __count_ != 0) 3217a984708SDavid Chisnall no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; 3227a984708SDavid Chisnall if (__count_ == 0) 3237a984708SDavid Chisnall { 3247a984708SDavid Chisnall __count_ = 1; 3257a984708SDavid Chisnall __id_ = __id; 3267a984708SDavid Chisnall return true; 3277a984708SDavid Chisnall } 3287a984708SDavid Chisnall return false; 3297a984708SDavid Chisnall} 3307a984708SDavid Chisnall 3317a984708SDavid Chisnalltemplate <class _L0, class _L1> 3327a984708SDavid Chisnallint 3337a984708SDavid Chisnalltry_lock(_L0& __l0, _L1& __l1) 3347a984708SDavid Chisnall{ 3357a984708SDavid Chisnall unique_lock<_L0> __u0(__l0, try_to_lock); 3367a984708SDavid Chisnall if (__u0.owns_lock()) 3377a984708SDavid Chisnall { 3387a984708SDavid Chisnall if (__l1.try_lock()) 3397a984708SDavid Chisnall { 3407a984708SDavid Chisnall __u0.release(); 3417a984708SDavid Chisnall return -1; 3427a984708SDavid Chisnall } 3437a984708SDavid Chisnall else 3447a984708SDavid Chisnall return 1; 3457a984708SDavid Chisnall } 3467a984708SDavid Chisnall return 0; 3477a984708SDavid Chisnall} 3487a984708SDavid Chisnall 349540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 3507a984708SDavid Chisnall 3517a984708SDavid Chisnalltemplate <class _L0, class _L1, class _L2, class... _L3> 3527a984708SDavid Chisnallint 3537a984708SDavid Chisnalltry_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) 3547a984708SDavid Chisnall{ 3557a984708SDavid Chisnall int __r = 0; 3567a984708SDavid Chisnall unique_lock<_L0> __u0(__l0, try_to_lock); 3577a984708SDavid Chisnall if (__u0.owns_lock()) 3587a984708SDavid Chisnall { 3597a984708SDavid Chisnall __r = try_lock(__l1, __l2, __l3...); 3607a984708SDavid Chisnall if (__r == -1) 3617a984708SDavid Chisnall __u0.release(); 3627a984708SDavid Chisnall else 3637a984708SDavid Chisnall ++__r; 3647a984708SDavid Chisnall } 3657a984708SDavid Chisnall return __r; 3667a984708SDavid Chisnall} 3677a984708SDavid Chisnall 368540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 3697a984708SDavid Chisnall 3707a984708SDavid Chisnalltemplate <class _L0, class _L1> 3717a984708SDavid Chisnallvoid 3727a984708SDavid Chisnalllock(_L0& __l0, _L1& __l1) 3737a984708SDavid Chisnall{ 3747a984708SDavid Chisnall while (true) 3757a984708SDavid Chisnall { 3767a984708SDavid Chisnall { 3777a984708SDavid Chisnall unique_lock<_L0> __u0(__l0); 3787a984708SDavid Chisnall if (__l1.try_lock()) 3797a984708SDavid Chisnall { 3807a984708SDavid Chisnall __u0.release(); 3817a984708SDavid Chisnall break; 3827a984708SDavid Chisnall } 3837a984708SDavid Chisnall } 3847c82a1ecSDimitry Andric __libcpp_thread_yield(); 3857a984708SDavid Chisnall { 3867a984708SDavid Chisnall unique_lock<_L1> __u1(__l1); 3877a984708SDavid Chisnall if (__l0.try_lock()) 3887a984708SDavid Chisnall { 3897a984708SDavid Chisnall __u1.release(); 3907a984708SDavid Chisnall break; 3917a984708SDavid Chisnall } 3927a984708SDavid Chisnall } 3937c82a1ecSDimitry Andric __libcpp_thread_yield(); 3947a984708SDavid Chisnall } 3957a984708SDavid Chisnall} 3967a984708SDavid Chisnall 397540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 3987a984708SDavid Chisnall 3997a984708SDavid Chisnalltemplate <class _L0, class _L1, class _L2, class ..._L3> 4007a984708SDavid Chisnallvoid 4017a984708SDavid Chisnall__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 4027a984708SDavid Chisnall{ 4037a984708SDavid Chisnall while (true) 4047a984708SDavid Chisnall { 4057a984708SDavid Chisnall switch (__i) 4067a984708SDavid Chisnall { 4077a984708SDavid Chisnall case 0: 4087a984708SDavid Chisnall { 4097a984708SDavid Chisnall unique_lock<_L0> __u0(__l0); 4107a984708SDavid Chisnall __i = try_lock(__l1, __l2, __l3...); 4117a984708SDavid Chisnall if (__i == -1) 4127a984708SDavid Chisnall { 4137a984708SDavid Chisnall __u0.release(); 4147a984708SDavid Chisnall return; 4157a984708SDavid Chisnall } 4167a984708SDavid Chisnall } 4177a984708SDavid Chisnall ++__i; 4187c82a1ecSDimitry Andric __libcpp_thread_yield(); 4197a984708SDavid Chisnall break; 4207a984708SDavid Chisnall case 1: 4217a984708SDavid Chisnall { 4227a984708SDavid Chisnall unique_lock<_L1> __u1(__l1); 4237a984708SDavid Chisnall __i = try_lock(__l2, __l3..., __l0); 4247a984708SDavid Chisnall if (__i == -1) 4257a984708SDavid Chisnall { 4267a984708SDavid Chisnall __u1.release(); 4277a984708SDavid Chisnall return; 4287a984708SDavid Chisnall } 4297a984708SDavid Chisnall } 4307a984708SDavid Chisnall if (__i == sizeof...(_L3) + 1) 4317a984708SDavid Chisnall __i = 0; 4327a984708SDavid Chisnall else 4337a984708SDavid Chisnall __i += 2; 4347c82a1ecSDimitry Andric __libcpp_thread_yield(); 4357a984708SDavid Chisnall break; 4367a984708SDavid Chisnall default: 4377a984708SDavid Chisnall __lock_first(__i - 2, __l2, __l3..., __l0, __l1); 4387a984708SDavid Chisnall return; 4397a984708SDavid Chisnall } 4407a984708SDavid Chisnall } 4417a984708SDavid Chisnall} 4427a984708SDavid Chisnall 4437a984708SDavid Chisnalltemplate <class _L0, class _L1, class _L2, class ..._L3> 4447a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY 4457a984708SDavid Chisnallvoid 4467a984708SDavid Chisnalllock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) 4477a984708SDavid Chisnall{ 4487a984708SDavid Chisnall __lock_first(0, __l0, __l1, __l2, __l3...); 4497a984708SDavid Chisnall} 4507a984708SDavid Chisnall 4517c82a1ecSDimitry Andrictemplate <class _L0> 4527c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4537c82a1ecSDimitry Andricvoid __unlock(_L0& __l0) { 4547c82a1ecSDimitry Andric __l0.unlock(); 4557c82a1ecSDimitry Andric} 4567c82a1ecSDimitry Andric 4577c82a1ecSDimitry Andrictemplate <class _L0, class _L1> 4587c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4597c82a1ecSDimitry Andricvoid __unlock(_L0& __l0, _L1& __l1) { 4607c82a1ecSDimitry Andric __l0.unlock(); 4617c82a1ecSDimitry Andric __l1.unlock(); 4627c82a1ecSDimitry Andric} 4637c82a1ecSDimitry Andric 4647c82a1ecSDimitry Andrictemplate <class _L0, class _L1, class _L2, class ..._L3> 4657c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4667c82a1ecSDimitry Andricvoid __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { 4677c82a1ecSDimitry Andric __l0.unlock(); 4687c82a1ecSDimitry Andric __l1.unlock(); 4697c82a1ecSDimitry Andric _VSTD::__unlock(__l2, __l3...); 4707c82a1ecSDimitry Andric} 4717c82a1ecSDimitry Andric 472540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 4737a984708SDavid Chisnall 474540d2a8bSDimitry Andric#if _LIBCPP_STD_VER > 14 475540d2a8bSDimitry Andrictemplate <class ..._Mutexes> 476540d2a8bSDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock; 477540d2a8bSDimitry Andric 478540d2a8bSDimitry Andrictemplate <> 479540d2a8bSDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock<> { 480540d2a8bSDimitry Andricpublic: 481540d2a8bSDimitry Andric explicit scoped_lock() {} 482540d2a8bSDimitry Andric ~scoped_lock() = default; 483540d2a8bSDimitry Andric 484540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 485540d2a8bSDimitry Andric explicit scoped_lock(adopt_lock_t) {} 486540d2a8bSDimitry Andric 487540d2a8bSDimitry Andric scoped_lock(scoped_lock const&) = delete; 488540d2a8bSDimitry Andric scoped_lock& operator=(scoped_lock const&) = delete; 489540d2a8bSDimitry Andric}; 490540d2a8bSDimitry Andric 491540d2a8bSDimitry Andrictemplate <class _Mutex> 492b5893f02SDimitry Andricclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> { 493540d2a8bSDimitry Andricpublic: 494540d2a8bSDimitry Andric typedef _Mutex mutex_type; 495540d2a8bSDimitry Andricprivate: 496540d2a8bSDimitry Andric mutex_type& __m_; 497540d2a8bSDimitry Andricpublic: 498540d2a8bSDimitry Andric explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 499540d2a8bSDimitry Andric : __m_(__m) {__m_.lock();} 500540d2a8bSDimitry Andric 501540d2a8bSDimitry Andric ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 502540d2a8bSDimitry Andric 503540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 5049dc417c3SDimitry Andric explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 505540d2a8bSDimitry Andric : __m_(__m) {} 506540d2a8bSDimitry Andric 507540d2a8bSDimitry Andric scoped_lock(scoped_lock const&) = delete; 508540d2a8bSDimitry Andric scoped_lock& operator=(scoped_lock const&) = delete; 509540d2a8bSDimitry Andric}; 510540d2a8bSDimitry Andric 511540d2a8bSDimitry Andrictemplate <class ..._MArgs> 512540d2a8bSDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock 513540d2a8bSDimitry Andric{ 514540d2a8bSDimitry Andric static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required"); 515540d2a8bSDimitry Andric typedef tuple<_MArgs&...> _MutexTuple; 516540d2a8bSDimitry Andric 517540d2a8bSDimitry Andricpublic: 518540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 519540d2a8bSDimitry Andric explicit scoped_lock(_MArgs&... __margs) 520540d2a8bSDimitry Andric : __t_(__margs...) 521540d2a8bSDimitry Andric { 522540d2a8bSDimitry Andric _VSTD::lock(__margs...); 523540d2a8bSDimitry Andric } 524540d2a8bSDimitry Andric 525540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 5269dc417c3SDimitry Andric scoped_lock(adopt_lock_t, _MArgs&... __margs) 527540d2a8bSDimitry Andric : __t_(__margs...) 528540d2a8bSDimitry Andric { 529540d2a8bSDimitry Andric } 530540d2a8bSDimitry Andric 531540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 532540d2a8bSDimitry Andric ~scoped_lock() { 533540d2a8bSDimitry Andric typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; 534540d2a8bSDimitry Andric __unlock_unpack(_Indices{}, __t_); 535540d2a8bSDimitry Andric } 536540d2a8bSDimitry Andric 537540d2a8bSDimitry Andric scoped_lock(scoped_lock const&) = delete; 538540d2a8bSDimitry Andric scoped_lock& operator=(scoped_lock const&) = delete; 539540d2a8bSDimitry Andric 540540d2a8bSDimitry Andricprivate: 541540d2a8bSDimitry Andric template <size_t ..._Indx> 542540d2a8bSDimitry Andric _LIBCPP_INLINE_VISIBILITY 543540d2a8bSDimitry Andric static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { 544540d2a8bSDimitry Andric _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...); 545540d2a8bSDimitry Andric } 546540d2a8bSDimitry Andric 547540d2a8bSDimitry Andric _MutexTuple __t_; 548540d2a8bSDimitry Andric}; 549540d2a8bSDimitry Andric 550540d2a8bSDimitry Andric#endif // _LIBCPP_STD_VER > 14 551d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 552d72607e9SDimitry Andric 553aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS once_flag; 5547a984708SDavid Chisnall 555540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 5567a984708SDavid Chisnall 5577a984708SDavid Chisnalltemplate<class _Callable, class... _Args> 558936e9439SDimitry Andric_LIBCPP_INLINE_VISIBILITY 5597a984708SDavid Chisnallvoid call_once(once_flag&, _Callable&&, _Args&&...); 5607a984708SDavid Chisnall 561540d2a8bSDimitry Andric#else // _LIBCPP_CXX03_LANG 5627a984708SDavid Chisnall 5637a984708SDavid Chisnalltemplate<class _Callable> 564936e9439SDimitry Andric_LIBCPP_INLINE_VISIBILITY 565854fa44bSDimitry Andricvoid call_once(once_flag&, _Callable&); 566854fa44bSDimitry Andric 567854fa44bSDimitry Andrictemplate<class _Callable> 568854fa44bSDimitry Andric_LIBCPP_INLINE_VISIBILITY 569854fa44bSDimitry Andricvoid call_once(once_flag&, const _Callable&); 5707a984708SDavid Chisnall 571540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 5727a984708SDavid Chisnall 573aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS once_flag 5747a984708SDavid Chisnall{ 5757a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 576936e9439SDimitry Andric _LIBCPP_CONSTEXPR 577936e9439SDimitry Andric once_flag() _NOEXCEPT : __state_(0) {} 5787a984708SDavid Chisnall 5797a984708SDavid Chisnallprivate: 5807a984708SDavid Chisnall once_flag(const once_flag&); // = delete; 5817a984708SDavid Chisnall once_flag& operator=(const once_flag&); // = delete; 5827a984708SDavid Chisnall 5837a984708SDavid Chisnall unsigned long __state_; 5847a984708SDavid Chisnall 585540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 5867a984708SDavid Chisnall template<class _Callable, class... _Args> 5877a984708SDavid Chisnall friend 5887a984708SDavid Chisnall void call_once(once_flag&, _Callable&&, _Args&&...); 589540d2a8bSDimitry Andric#else // _LIBCPP_CXX03_LANG 5907a984708SDavid Chisnall template<class _Callable> 5917a984708SDavid Chisnall friend 592854fa44bSDimitry Andric void call_once(once_flag&, _Callable&); 593854fa44bSDimitry Andric 594854fa44bSDimitry Andric template<class _Callable> 595854fa44bSDimitry Andric friend 596854fa44bSDimitry Andric void call_once(once_flag&, const _Callable&); 597540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 5987a984708SDavid Chisnall}; 5997a984708SDavid Chisnall 600540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 6017a984708SDavid Chisnall 60294e3ee44SDavid Chisnalltemplate <class _Fp> 6037a984708SDavid Chisnallclass __call_once_param 6047a984708SDavid Chisnall{ 605854fa44bSDimitry Andric _Fp& __f_; 6067a984708SDavid Chisnallpublic: 6077a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 608854fa44bSDimitry Andric explicit __call_once_param(_Fp& __f) : __f_(__f) {} 6097a984708SDavid Chisnall 6107a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 6117a984708SDavid Chisnall void operator()() 6127a984708SDavid Chisnall { 61394e3ee44SDavid Chisnall typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 6147a984708SDavid Chisnall __execute(_Index()); 6157a984708SDavid Chisnall } 6167a984708SDavid Chisnall 6177a984708SDavid Chisnallprivate: 6187a984708SDavid Chisnall template <size_t ..._Indices> 6197a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 6207a984708SDavid Chisnall void __execute(__tuple_indices<_Indices...>) 6217a984708SDavid Chisnall { 622854fa44bSDimitry Andric __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...); 6237a984708SDavid Chisnall } 6247a984708SDavid Chisnall}; 6257a984708SDavid Chisnall 6267a984708SDavid Chisnall#else 6277a984708SDavid Chisnall 62894e3ee44SDavid Chisnalltemplate <class _Fp> 6297a984708SDavid Chisnallclass __call_once_param 6307a984708SDavid Chisnall{ 631854fa44bSDimitry Andric _Fp& __f_; 6327a984708SDavid Chisnallpublic: 6337a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 634854fa44bSDimitry Andric explicit __call_once_param(_Fp& __f) : __f_(__f) {} 6357a984708SDavid Chisnall 6367a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY 6377a984708SDavid Chisnall void operator()() 6387a984708SDavid Chisnall { 6397a984708SDavid Chisnall __f_(); 6407a984708SDavid Chisnall } 6417a984708SDavid Chisnall}; 6427a984708SDavid Chisnall 6437a984708SDavid Chisnall#endif 6447a984708SDavid Chisnall 64594e3ee44SDavid Chisnalltemplate <class _Fp> 6467a984708SDavid Chisnallvoid 6477a984708SDavid Chisnall__call_once_proxy(void* __vp) 6487a984708SDavid Chisnall{ 64994e3ee44SDavid Chisnall __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); 6507a984708SDavid Chisnall (*__p)(); 6517a984708SDavid Chisnall} 6527a984708SDavid Chisnall 6534f7ab58eSDimitry Andric_LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*)); 6547a984708SDavid Chisnall 655540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 6567a984708SDavid Chisnall 6577a984708SDavid Chisnalltemplate<class _Callable, class... _Args> 6587a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY 6597a984708SDavid Chisnallvoid 6607a984708SDavid Chisnallcall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) 6617a984708SDavid Chisnall{ 662aed8d94eSDimitry Andric if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) 6637a984708SDavid Chisnall { 664854fa44bSDimitry Andric typedef tuple<_Callable&&, _Args&&...> _Gp; 665854fa44bSDimitry Andric _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...); 666854fa44bSDimitry Andric __call_once_param<_Gp> __p(__f); 66794e3ee44SDavid Chisnall __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); 6687a984708SDavid Chisnall } 6697a984708SDavid Chisnall} 6707a984708SDavid Chisnall 671540d2a8bSDimitry Andric#else // _LIBCPP_CXX03_LANG 6727a984708SDavid Chisnall 6737a984708SDavid Chisnalltemplate<class _Callable> 6747a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY 6757a984708SDavid Chisnallvoid 676854fa44bSDimitry Andriccall_once(once_flag& __flag, _Callable& __func) 6777a984708SDavid Chisnall{ 678aed8d94eSDimitry Andric if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) 6797a984708SDavid Chisnall { 6807a984708SDavid Chisnall __call_once_param<_Callable> __p(__func); 6817a984708SDavid Chisnall __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); 6827a984708SDavid Chisnall } 6837a984708SDavid Chisnall} 6847a984708SDavid Chisnall 685854fa44bSDimitry Andrictemplate<class _Callable> 686854fa44bSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 687854fa44bSDimitry Andricvoid 688854fa44bSDimitry Andriccall_once(once_flag& __flag, const _Callable& __func) 689854fa44bSDimitry Andric{ 69051690af2SDimitry Andric if (__libcpp_acquire_load(&__flag.__state_) != ~0ul) 691854fa44bSDimitry Andric { 692854fa44bSDimitry Andric __call_once_param<const _Callable> __p(__func); 693854fa44bSDimitry Andric __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>); 694854fa44bSDimitry Andric } 695854fa44bSDimitry Andric} 696854fa44bSDimitry Andric 697540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 6987c82a1ecSDimitry Andric 6997a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD 7007a984708SDavid Chisnall 701f9448bf3SDimitry Andric_LIBCPP_POP_MACROS 702f9448bf3SDimitry Andric 7037a984708SDavid Chisnall#endif // _LIBCPP_MUTEX 704