xref: /freebsd/contrib/llvm-project/libcxx/include/mutex (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_MUTEX
110b57cec5SDimitry Andric#define _LIBCPP_MUTEX
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    mutex synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andricnamespace std
170b57cec5SDimitry Andric{
180b57cec5SDimitry Andric
190b57cec5SDimitry Andricclass mutex
200b57cec5SDimitry Andric{
210b57cec5SDimitry Andricpublic:
220b57cec5SDimitry Andric     constexpr mutex() noexcept;
230b57cec5SDimitry Andric     ~mutex();
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric    mutex(const mutex&) = delete;
260b57cec5SDimitry Andric    mutex& operator=(const mutex&) = delete;
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric    void lock();
290b57cec5SDimitry Andric    bool try_lock();
300b57cec5SDimitry Andric    void unlock();
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric    typedef pthread_mutex_t* native_handle_type;
330b57cec5SDimitry Andric    native_handle_type native_handle();
340b57cec5SDimitry Andric};
350b57cec5SDimitry Andric
360b57cec5SDimitry Andricclass recursive_mutex
370b57cec5SDimitry Andric{
380b57cec5SDimitry Andricpublic:
390b57cec5SDimitry Andric     recursive_mutex();
400b57cec5SDimitry Andric     ~recursive_mutex();
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric    recursive_mutex(const recursive_mutex&) = delete;
430b57cec5SDimitry Andric    recursive_mutex& operator=(const recursive_mutex&) = delete;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric    void lock();
460b57cec5SDimitry Andric    bool try_lock() noexcept;
470b57cec5SDimitry Andric    void unlock();
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric    typedef pthread_mutex_t* native_handle_type;
500b57cec5SDimitry Andric    native_handle_type native_handle();
510b57cec5SDimitry Andric};
520b57cec5SDimitry Andric
530b57cec5SDimitry Andricclass timed_mutex
540b57cec5SDimitry Andric{
550b57cec5SDimitry Andricpublic:
560b57cec5SDimitry Andric     timed_mutex();
570b57cec5SDimitry Andric     ~timed_mutex();
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric    timed_mutex(const timed_mutex&) = delete;
600b57cec5SDimitry Andric    timed_mutex& operator=(const timed_mutex&) = delete;
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric    void lock();
630b57cec5SDimitry Andric    bool try_lock();
640b57cec5SDimitry Andric    template <class Rep, class Period>
650b57cec5SDimitry Andric        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
660b57cec5SDimitry Andric    template <class Clock, class Duration>
670b57cec5SDimitry Andric        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
680b57cec5SDimitry Andric    void unlock();
690b57cec5SDimitry Andric};
700b57cec5SDimitry Andric
710b57cec5SDimitry Andricclass recursive_timed_mutex
720b57cec5SDimitry Andric{
730b57cec5SDimitry Andricpublic:
740b57cec5SDimitry Andric     recursive_timed_mutex();
750b57cec5SDimitry Andric     ~recursive_timed_mutex();
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
780b57cec5SDimitry Andric    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric    void lock();
810b57cec5SDimitry Andric    bool try_lock() noexcept;
820b57cec5SDimitry Andric    template <class Rep, class Period>
830b57cec5SDimitry Andric        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
840b57cec5SDimitry Andric    template <class Clock, class Duration>
850b57cec5SDimitry Andric        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
860b57cec5SDimitry Andric    void unlock();
870b57cec5SDimitry Andric};
880b57cec5SDimitry Andric
89e40139ffSDimitry Andricstruct defer_lock_t { explicit defer_lock_t() = default; };
90e40139ffSDimitry Andricstruct try_to_lock_t { explicit try_to_lock_t() = default; };
91e40139ffSDimitry Andricstruct adopt_lock_t { explicit adopt_lock_t() = default; };
920b57cec5SDimitry Andric
930b57cec5SDimitry Andricinline constexpr defer_lock_t  defer_lock{};
940b57cec5SDimitry Andricinline constexpr try_to_lock_t try_to_lock{};
950b57cec5SDimitry Andricinline constexpr adopt_lock_t  adopt_lock{};
960b57cec5SDimitry Andric
970b57cec5SDimitry Andrictemplate <class Mutex>
980b57cec5SDimitry Andricclass lock_guard
990b57cec5SDimitry Andric{
1000b57cec5SDimitry Andricpublic:
1010b57cec5SDimitry Andric    typedef Mutex mutex_type;
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric    explicit lock_guard(mutex_type& m);
1040b57cec5SDimitry Andric    lock_guard(mutex_type& m, adopt_lock_t);
1050b57cec5SDimitry Andric    ~lock_guard();
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric    lock_guard(lock_guard const&) = delete;
1080b57cec5SDimitry Andric    lock_guard& operator=(lock_guard const&) = delete;
1090b57cec5SDimitry Andric};
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andrictemplate <class... MutexTypes>
1120b57cec5SDimitry Andricclass scoped_lock // C++17
1130b57cec5SDimitry Andric{
1140b57cec5SDimitry Andricpublic:
115349cc55cSDimitry Andric    using mutex_type = Mutex;  // Only if sizeof...(MutexTypes) == 1
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric    explicit scoped_lock(MutexTypes&... m);
1180b57cec5SDimitry Andric    scoped_lock(adopt_lock_t, MutexTypes&... m);
1190b57cec5SDimitry Andric    ~scoped_lock();
1200b57cec5SDimitry Andric    scoped_lock(scoped_lock const&) = delete;
1210b57cec5SDimitry Andric    scoped_lock& operator=(scoped_lock const&) = delete;
1220b57cec5SDimitry Andricprivate:
1230b57cec5SDimitry Andric    tuple<MutexTypes&...> pm; // exposition only
1240b57cec5SDimitry Andric};
1250b57cec5SDimitry Andric
1260b57cec5SDimitry Andrictemplate <class Mutex>
1270b57cec5SDimitry Andricclass unique_lock
1280b57cec5SDimitry Andric{
1290b57cec5SDimitry Andricpublic:
1300b57cec5SDimitry Andric    typedef Mutex mutex_type;
1310b57cec5SDimitry Andric    unique_lock() noexcept;
1320b57cec5SDimitry Andric    explicit unique_lock(mutex_type& m);
1330b57cec5SDimitry Andric    unique_lock(mutex_type& m, defer_lock_t) noexcept;
1340b57cec5SDimitry Andric    unique_lock(mutex_type& m, try_to_lock_t);
1350b57cec5SDimitry Andric    unique_lock(mutex_type& m, adopt_lock_t);
1360b57cec5SDimitry Andric    template <class Clock, class Duration>
1370b57cec5SDimitry Andric        unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
1380b57cec5SDimitry Andric    template <class Rep, class Period>
1390b57cec5SDimitry Andric        unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
1400b57cec5SDimitry Andric    ~unique_lock();
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric    unique_lock(unique_lock const&) = delete;
1430b57cec5SDimitry Andric    unique_lock& operator=(unique_lock const&) = delete;
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric    unique_lock(unique_lock&& u) noexcept;
1460b57cec5SDimitry Andric    unique_lock& operator=(unique_lock&& u) noexcept;
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric    void lock();
1490b57cec5SDimitry Andric    bool try_lock();
1500b57cec5SDimitry Andric
1510b57cec5SDimitry Andric    template <class Rep, class Period>
1520b57cec5SDimitry Andric        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1530b57cec5SDimitry Andric    template <class Clock, class Duration>
1540b57cec5SDimitry Andric        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric    void unlock();
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andric    void swap(unique_lock& u) noexcept;
1590b57cec5SDimitry Andric    mutex_type* release() noexcept;
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric    bool owns_lock() const noexcept;
1620b57cec5SDimitry Andric    explicit operator bool () const noexcept;
1630b57cec5SDimitry Andric    mutex_type* mutex() const noexcept;
1640b57cec5SDimitry Andric};
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andrictemplate <class Mutex>
1670b57cec5SDimitry Andric  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andrictemplate <class L1, class L2, class... L3>
1700b57cec5SDimitry Andric  int try_lock(L1&, L2&, L3&...);
1710b57cec5SDimitry Andrictemplate <class L1, class L2, class... L3>
1720b57cec5SDimitry Andric  void lock(L1&, L2&, L3&...);
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andricstruct once_flag
1750b57cec5SDimitry Andric{
1760b57cec5SDimitry Andric    constexpr once_flag() noexcept;
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric    once_flag(const once_flag&) = delete;
1790b57cec5SDimitry Andric    once_flag& operator=(const once_flag&) = delete;
1800b57cec5SDimitry Andric};
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andrictemplate<class Callable, class ...Args>
1830b57cec5SDimitry Andric  void call_once(once_flag& flag, Callable&& func, Args&&... args);
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric}  // std
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric*/
1880b57cec5SDimitry Andric
18981ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
1900b57cec5SDimitry Andric#include <__config>
191*bdd1243dSDimitry Andric#include <__memory/shared_ptr.h>
1920b57cec5SDimitry Andric#include <__mutex_base>
193fe6060f1SDimitry Andric#include <__threading_support>
194fe6060f1SDimitry Andric#include <__utility/forward.h>
1950b57cec5SDimitry Andric#include <cstdint>
1960b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
1970b57cec5SDimitry Andric# include <tuple>
1980b57cec5SDimitry Andric#endif
1990b57cec5SDimitry Andric#include <version>
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2020b57cec5SDimitry Andric#  pragma GCC system_header
2030b57cec5SDimitry Andric#endif
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS
2060b57cec5SDimitry Andric#include <__undef_macros>
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_THREADS
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS recursive_mutex
2140b57cec5SDimitry Andric{
2150b57cec5SDimitry Andric    __libcpp_recursive_mutex_t __m_;
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andricpublic:
2180b57cec5SDimitry Andric    recursive_mutex();
2190b57cec5SDimitry Andric    ~recursive_mutex();
2200b57cec5SDimitry Andric
2210eae32dcSDimitry Andric    recursive_mutex(const recursive_mutex&) = delete;
2220eae32dcSDimitry Andric    recursive_mutex& operator=(const recursive_mutex&) = delete;
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric    void lock();
2250b57cec5SDimitry Andric    bool try_lock() _NOEXCEPT;
2260b57cec5SDimitry Andric    void unlock()  _NOEXCEPT;
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric    typedef __libcpp_recursive_mutex_t* native_handle_type;
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2310b57cec5SDimitry Andric    native_handle_type native_handle() {return &__m_;}
2320b57cec5SDimitry Andric};
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS timed_mutex
2350b57cec5SDimitry Andric{
2360b57cec5SDimitry Andric    mutex              __m_;
2370b57cec5SDimitry Andric    condition_variable __cv_;
2380b57cec5SDimitry Andric    bool               __locked_;
2390b57cec5SDimitry Andricpublic:
2400b57cec5SDimitry Andric     timed_mutex();
2410b57cec5SDimitry Andric     ~timed_mutex();
2420b57cec5SDimitry Andric
2430eae32dcSDimitry Andric    timed_mutex(const timed_mutex&) = delete;
2440eae32dcSDimitry Andric    timed_mutex& operator=(const timed_mutex&) = delete;
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andricpublic:
2470b57cec5SDimitry Andric    void lock();
2480b57cec5SDimitry Andric    bool try_lock() _NOEXCEPT;
2490b57cec5SDimitry Andric    template <class _Rep, class _Period>
2500b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
2510b57cec5SDimitry Andric        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
2520b57cec5SDimitry Andric            {return try_lock_until(chrono::steady_clock::now() + __d);}
2530b57cec5SDimitry Andric    template <class _Clock, class _Duration>
2540b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
2550b57cec5SDimitry Andric        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
2560b57cec5SDimitry Andric    void unlock() _NOEXCEPT;
2570b57cec5SDimitry Andric};
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andrictemplate <class _Clock, class _Duration>
2600b57cec5SDimitry Andricbool
2610b57cec5SDimitry Andrictimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
2620b57cec5SDimitry Andric{
2630b57cec5SDimitry Andric    using namespace chrono;
2640b57cec5SDimitry Andric    unique_lock<mutex> __lk(__m_);
2650b57cec5SDimitry Andric    bool no_timeout = _Clock::now() < __t;
2660b57cec5SDimitry Andric    while (no_timeout && __locked_)
2670b57cec5SDimitry Andric        no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
2680b57cec5SDimitry Andric    if (!__locked_)
2690b57cec5SDimitry Andric    {
2700b57cec5SDimitry Andric        __locked_ = true;
2710b57cec5SDimitry Andric        return true;
2720b57cec5SDimitry Andric    }
2730b57cec5SDimitry Andric    return false;
2740b57cec5SDimitry Andric}
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS recursive_timed_mutex
2770b57cec5SDimitry Andric{
2780b57cec5SDimitry Andric    mutex              __m_;
2790b57cec5SDimitry Andric    condition_variable __cv_;
2800b57cec5SDimitry Andric    size_t             __count_;
2810b57cec5SDimitry Andric    __thread_id        __id_;
2820b57cec5SDimitry Andricpublic:
2830b57cec5SDimitry Andric    recursive_timed_mutex();
2840b57cec5SDimitry Andric    ~recursive_timed_mutex();
2850b57cec5SDimitry Andric
2860eae32dcSDimitry Andric    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
2870eae32dcSDimitry Andric    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric    void lock();
2900b57cec5SDimitry Andric    bool try_lock() _NOEXCEPT;
2910b57cec5SDimitry Andric    template <class _Rep, class _Period>
2920b57cec5SDimitry Andric        _LIBCPP_INLINE_VISIBILITY
2930b57cec5SDimitry Andric        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
2940b57cec5SDimitry Andric            {return try_lock_until(chrono::steady_clock::now() + __d);}
2950b57cec5SDimitry Andric    template <class _Clock, class _Duration>
2960b57cec5SDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
2970b57cec5SDimitry Andric        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
2980b57cec5SDimitry Andric    void unlock() _NOEXCEPT;
2990b57cec5SDimitry Andric};
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andrictemplate <class _Clock, class _Duration>
3020b57cec5SDimitry Andricbool
3030b57cec5SDimitry Andricrecursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
3040b57cec5SDimitry Andric{
3050b57cec5SDimitry Andric    using namespace chrono;
3060b57cec5SDimitry Andric    __thread_id __id = this_thread::get_id();
3070b57cec5SDimitry Andric    unique_lock<mutex> lk(__m_);
3080b57cec5SDimitry Andric    if (__id == __id_)
3090b57cec5SDimitry Andric    {
3100b57cec5SDimitry Andric        if (__count_ == numeric_limits<size_t>::max())
3110b57cec5SDimitry Andric            return false;
3120b57cec5SDimitry Andric        ++__count_;
3130b57cec5SDimitry Andric        return true;
3140b57cec5SDimitry Andric    }
3150b57cec5SDimitry Andric    bool no_timeout = _Clock::now() < __t;
3160b57cec5SDimitry Andric    while (no_timeout && __count_ != 0)
3170b57cec5SDimitry Andric        no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
3180b57cec5SDimitry Andric    if (__count_ == 0)
3190b57cec5SDimitry Andric    {
3200b57cec5SDimitry Andric        __count_ = 1;
3210b57cec5SDimitry Andric        __id_ = __id;
3220b57cec5SDimitry Andric        return true;
3230b57cec5SDimitry Andric    }
3240b57cec5SDimitry Andric    return false;
3250b57cec5SDimitry Andric}
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andrictemplate <class _L0, class _L1>
328*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI int
3290b57cec5SDimitry Andrictry_lock(_L0& __l0, _L1& __l1)
3300b57cec5SDimitry Andric{
3310b57cec5SDimitry Andric    unique_lock<_L0> __u0(__l0, try_to_lock);
3320b57cec5SDimitry Andric    if (__u0.owns_lock())
3330b57cec5SDimitry Andric    {
3340b57cec5SDimitry Andric        if (__l1.try_lock())
3350b57cec5SDimitry Andric        {
3360b57cec5SDimitry Andric            __u0.release();
3370b57cec5SDimitry Andric            return -1;
3380b57cec5SDimitry Andric        }
3390b57cec5SDimitry Andric        else
3400b57cec5SDimitry Andric            return 1;
3410b57cec5SDimitry Andric    }
3420b57cec5SDimitry Andric    return 0;
3430b57cec5SDimitry Andric}
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andrictemplate <class _L0, class _L1, class _L2, class... _L3>
348*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI int
3490b57cec5SDimitry Andrictry_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
3500b57cec5SDimitry Andric{
3510b57cec5SDimitry Andric    int __r = 0;
3520b57cec5SDimitry Andric    unique_lock<_L0> __u0(__l0, try_to_lock);
3530b57cec5SDimitry Andric    if (__u0.owns_lock())
3540b57cec5SDimitry Andric    {
355*bdd1243dSDimitry Andric        __r = std::try_lock(__l1, __l2, __l3...);
3560b57cec5SDimitry Andric        if (__r == -1)
3570b57cec5SDimitry Andric            __u0.release();
3580b57cec5SDimitry Andric        else
3590b57cec5SDimitry Andric            ++__r;
3600b57cec5SDimitry Andric    }
3610b57cec5SDimitry Andric    return __r;
3620b57cec5SDimitry Andric}
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andrictemplate <class _L0, class _L1>
367*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI void
3680b57cec5SDimitry Andriclock(_L0& __l0, _L1& __l1)
3690b57cec5SDimitry Andric{
3700b57cec5SDimitry Andric    while (true)
3710b57cec5SDimitry Andric    {
3720b57cec5SDimitry Andric        {
3730b57cec5SDimitry Andric            unique_lock<_L0> __u0(__l0);
3740b57cec5SDimitry Andric            if (__l1.try_lock())
3750b57cec5SDimitry Andric            {
3760b57cec5SDimitry Andric                __u0.release();
3770b57cec5SDimitry Andric                break;
3780b57cec5SDimitry Andric            }
3790b57cec5SDimitry Andric        }
3800b57cec5SDimitry Andric        __libcpp_thread_yield();
3810b57cec5SDimitry Andric        {
3820b57cec5SDimitry Andric            unique_lock<_L1> __u1(__l1);
3830b57cec5SDimitry Andric            if (__l0.try_lock())
3840b57cec5SDimitry Andric            {
3850b57cec5SDimitry Andric                __u1.release();
3860b57cec5SDimitry Andric                break;
3870b57cec5SDimitry Andric            }
3880b57cec5SDimitry Andric        }
3890b57cec5SDimitry Andric        __libcpp_thread_yield();
3900b57cec5SDimitry Andric    }
3910b57cec5SDimitry Andric}
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andrictemplate <class _L0, class _L1, class _L2, class ..._L3>
3960b57cec5SDimitry Andricvoid
3970b57cec5SDimitry Andric__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
3980b57cec5SDimitry Andric{
3990b57cec5SDimitry Andric    while (true)
4000b57cec5SDimitry Andric    {
4010b57cec5SDimitry Andric        switch (__i)
4020b57cec5SDimitry Andric        {
4030b57cec5SDimitry Andric        case 0:
4040b57cec5SDimitry Andric            {
4050b57cec5SDimitry Andric                unique_lock<_L0> __u0(__l0);
406*bdd1243dSDimitry Andric                __i = std::try_lock(__l1, __l2, __l3...);
4070b57cec5SDimitry Andric                if (__i == -1)
4080b57cec5SDimitry Andric                {
4090b57cec5SDimitry Andric                    __u0.release();
4100b57cec5SDimitry Andric                    return;
4110b57cec5SDimitry Andric                }
4120b57cec5SDimitry Andric            }
4130b57cec5SDimitry Andric            ++__i;
4140b57cec5SDimitry Andric            __libcpp_thread_yield();
4150b57cec5SDimitry Andric            break;
4160b57cec5SDimitry Andric        case 1:
4170b57cec5SDimitry Andric            {
4180b57cec5SDimitry Andric                unique_lock<_L1> __u1(__l1);
419*bdd1243dSDimitry Andric                __i = std::try_lock(__l2, __l3..., __l0);
4200b57cec5SDimitry Andric                if (__i == -1)
4210b57cec5SDimitry Andric                {
4220b57cec5SDimitry Andric                    __u1.release();
4230b57cec5SDimitry Andric                    return;
4240b57cec5SDimitry Andric                }
4250b57cec5SDimitry Andric            }
4260b57cec5SDimitry Andric            if (__i == sizeof...(_L3) + 1)
4270b57cec5SDimitry Andric                __i = 0;
4280b57cec5SDimitry Andric            else
4290b57cec5SDimitry Andric                __i += 2;
4300b57cec5SDimitry Andric            __libcpp_thread_yield();
4310b57cec5SDimitry Andric            break;
4320b57cec5SDimitry Andric        default:
433*bdd1243dSDimitry Andric            std::__lock_first(__i - 2, __l2, __l3..., __l0, __l1);
4340b57cec5SDimitry Andric            return;
4350b57cec5SDimitry Andric        }
4360b57cec5SDimitry Andric    }
4370b57cec5SDimitry Andric}
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andrictemplate <class _L0, class _L1, class _L2, class ..._L3>
4400b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
4410b57cec5SDimitry Andricvoid
4420b57cec5SDimitry Andriclock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
4430b57cec5SDimitry Andric{
444*bdd1243dSDimitry Andric    std::__lock_first(0, __l0, __l1, __l2, __l3...);
4450b57cec5SDimitry Andric}
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andrictemplate <class _L0>
4480b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
4490b57cec5SDimitry Andricvoid __unlock(_L0& __l0) {
4500b57cec5SDimitry Andric    __l0.unlock();
4510b57cec5SDimitry Andric}
4520b57cec5SDimitry Andric
4530b57cec5SDimitry Andrictemplate <class _L0, class _L1>
4540b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
4550b57cec5SDimitry Andricvoid __unlock(_L0& __l0, _L1& __l1) {
4560b57cec5SDimitry Andric    __l0.unlock();
4570b57cec5SDimitry Andric    __l1.unlock();
4580b57cec5SDimitry Andric}
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andrictemplate <class _L0, class _L1, class _L2, class ..._L3>
4610b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
4620b57cec5SDimitry Andricvoid __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
4630b57cec5SDimitry Andric    __l0.unlock();
4640b57cec5SDimitry Andric    __l1.unlock();
4650b57cec5SDimitry Andric    _VSTD::__unlock(__l2, __l3...);
4660b57cec5SDimitry Andric}
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 14
4710b57cec5SDimitry Andrictemplate <class ..._Mutexes>
4720b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock;
4730b57cec5SDimitry Andric
4740b57cec5SDimitry Andrictemplate <>
4750b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock<> {
4760b57cec5SDimitry Andricpublic:
4770b57cec5SDimitry Andric    explicit scoped_lock() {}
4780b57cec5SDimitry Andric    ~scoped_lock() = default;
4790b57cec5SDimitry Andric
4800b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4810b57cec5SDimitry Andric    explicit scoped_lock(adopt_lock_t) {}
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric    scoped_lock(scoped_lock const&) = delete;
4840b57cec5SDimitry Andric    scoped_lock& operator=(scoped_lock const&) = delete;
4850b57cec5SDimitry Andric};
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andrictemplate <class _Mutex>
4880b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
4890b57cec5SDimitry Andricpublic:
4900b57cec5SDimitry Andric    typedef _Mutex  mutex_type;
4910b57cec5SDimitry Andricprivate:
4920b57cec5SDimitry Andric    mutex_type& __m_;
4930b57cec5SDimitry Andricpublic:
4940b57cec5SDimitry Andric    explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
4950b57cec5SDimitry Andric        : __m_(__m) {__m_.lock();}
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andric    ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5000b57cec5SDimitry Andric    explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
5010b57cec5SDimitry Andric        : __m_(__m) {}
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric    scoped_lock(scoped_lock const&) = delete;
5040b57cec5SDimitry Andric    scoped_lock& operator=(scoped_lock const&) = delete;
5050b57cec5SDimitry Andric};
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andrictemplate <class ..._MArgs>
5080b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS scoped_lock
5090b57cec5SDimitry Andric{
5100b57cec5SDimitry Andric    static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
5110b57cec5SDimitry Andric    typedef tuple<_MArgs&...> _MutexTuple;
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andricpublic:
5140b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5150b57cec5SDimitry Andric    explicit scoped_lock(_MArgs&... __margs)
5160b57cec5SDimitry Andric      : __t_(__margs...)
5170b57cec5SDimitry Andric    {
5180b57cec5SDimitry Andric        _VSTD::lock(__margs...);
5190b57cec5SDimitry Andric    }
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5220b57cec5SDimitry Andric    scoped_lock(adopt_lock_t, _MArgs&... __margs)
5230b57cec5SDimitry Andric        : __t_(__margs...)
5240b57cec5SDimitry Andric    {
5250b57cec5SDimitry Andric    }
5260b57cec5SDimitry Andric
5270b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5280b57cec5SDimitry Andric    ~scoped_lock() {
5290b57cec5SDimitry Andric        typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
5300b57cec5SDimitry Andric        __unlock_unpack(_Indices{}, __t_);
5310b57cec5SDimitry Andric    }
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric    scoped_lock(scoped_lock const&) = delete;
5340b57cec5SDimitry Andric    scoped_lock& operator=(scoped_lock const&) = delete;
5350b57cec5SDimitry Andric
5360b57cec5SDimitry Andricprivate:
5370b57cec5SDimitry Andric    template <size_t ..._Indx>
5380b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5390b57cec5SDimitry Andric    static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
5400b57cec5SDimitry Andric        _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
5410b57cec5SDimitry Andric    }
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric    _MutexTuple __t_;
5440b57cec5SDimitry Andric};
545*bdd1243dSDimitry Andric_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock);
5460b57cec5SDimitry Andric
5470b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 14
5480b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS once_flag;
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andrictemplate<class _Callable, class... _Args>
5550b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
5560b57cec5SDimitry Andricvoid call_once(once_flag&, _Callable&&, _Args&&...);
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric#else  // _LIBCPP_CXX03_LANG
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andrictemplate<class _Callable>
5610b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
5620b57cec5SDimitry Andricvoid call_once(once_flag&, _Callable&);
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andrictemplate<class _Callable>
5650b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
5660b57cec5SDimitry Andricvoid call_once(once_flag&, const _Callable&);
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS once_flag
5710b57cec5SDimitry Andric{
5720b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5730b57cec5SDimitry Andric    _LIBCPP_CONSTEXPR
5740b57cec5SDimitry Andric        once_flag() _NOEXCEPT : __state_(0) {}
5750eae32dcSDimitry Andric    once_flag(const once_flag&) = delete;
5760eae32dcSDimitry Andric    once_flag& operator=(const once_flag&) = delete;
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric#if defined(_LIBCPP_ABI_MICROSOFT)
5790b57cec5SDimitry Andric   typedef uintptr_t _State_type;
5800b57cec5SDimitry Andric#else
5810b57cec5SDimitry Andric   typedef unsigned long _State_type;
5820b57cec5SDimitry Andric#endif
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andricprivate:
5850b57cec5SDimitry Andric    _State_type __state_;
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
5880b57cec5SDimitry Andric    template<class _Callable, class... _Args>
5890b57cec5SDimitry Andric    friend
5900b57cec5SDimitry Andric    void call_once(once_flag&, _Callable&&, _Args&&...);
5910b57cec5SDimitry Andric#else  // _LIBCPP_CXX03_LANG
5920b57cec5SDimitry Andric    template<class _Callable>
5930b57cec5SDimitry Andric    friend
5940b57cec5SDimitry Andric    void call_once(once_flag&, _Callable&);
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric    template<class _Callable>
5970b57cec5SDimitry Andric    friend
5980b57cec5SDimitry Andric    void call_once(once_flag&, const _Callable&);
5990b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG
6000b57cec5SDimitry Andric};
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andrictemplate <class _Fp>
6050b57cec5SDimitry Andricclass __call_once_param
6060b57cec5SDimitry Andric{
6070b57cec5SDimitry Andric    _Fp& __f_;
6080b57cec5SDimitry Andricpublic:
6090b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6100b57cec5SDimitry Andric    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6130b57cec5SDimitry Andric    void operator()()
6140b57cec5SDimitry Andric    {
6150b57cec5SDimitry Andric        typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
6160b57cec5SDimitry Andric        __execute(_Index());
6170b57cec5SDimitry Andric    }
6180b57cec5SDimitry Andric
6190b57cec5SDimitry Andricprivate:
6200b57cec5SDimitry Andric    template <size_t ..._Indices>
6210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6220b57cec5SDimitry Andric    void __execute(__tuple_indices<_Indices...>)
6230b57cec5SDimitry Andric    {
624e8d8bef9SDimitry Andric        _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
6250b57cec5SDimitry Andric    }
6260b57cec5SDimitry Andric};
6270b57cec5SDimitry Andric
6280b57cec5SDimitry Andric#else
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andrictemplate <class _Fp>
6310b57cec5SDimitry Andricclass __call_once_param
6320b57cec5SDimitry Andric{
6330b57cec5SDimitry Andric    _Fp& __f_;
6340b57cec5SDimitry Andricpublic:
6350b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6360b57cec5SDimitry Andric    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
6370b57cec5SDimitry Andric
6380b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6390b57cec5SDimitry Andric    void operator()()
6400b57cec5SDimitry Andric    {
6410b57cec5SDimitry Andric        __f_();
6420b57cec5SDimitry Andric    }
6430b57cec5SDimitry Andric};
6440b57cec5SDimitry Andric
6450b57cec5SDimitry Andric#endif
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andrictemplate <class _Fp>
648480093f4SDimitry Andricvoid _LIBCPP_INLINE_VISIBILITY
6490b57cec5SDimitry Andric__call_once_proxy(void* __vp)
6500b57cec5SDimitry Andric{
6510b57cec5SDimitry Andric    __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
6520b57cec5SDimitry Andric    (*__p)();
6530b57cec5SDimitry Andric}
6540b57cec5SDimitry Andric
6550b57cec5SDimitry Andric_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*,
6560b57cec5SDimitry Andric                                  void (*)(void*));
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG
6590b57cec5SDimitry Andric
6600b57cec5SDimitry Andrictemplate<class _Callable, class... _Args>
6610b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
6620b57cec5SDimitry Andricvoid
6630b57cec5SDimitry Andriccall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
6640b57cec5SDimitry Andric{
6650b57cec5SDimitry Andric    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
6660b57cec5SDimitry Andric    {
6670b57cec5SDimitry Andric        typedef tuple<_Callable&&, _Args&&...> _Gp;
6680b57cec5SDimitry Andric        _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
6690b57cec5SDimitry Andric        __call_once_param<_Gp> __p(__f);
670*bdd1243dSDimitry Andric        std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
6710b57cec5SDimitry Andric    }
6720b57cec5SDimitry Andric}
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric#else  // _LIBCPP_CXX03_LANG
6750b57cec5SDimitry Andric
6760b57cec5SDimitry Andrictemplate<class _Callable>
6770b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
6780b57cec5SDimitry Andricvoid
6790b57cec5SDimitry Andriccall_once(once_flag& __flag, _Callable& __func)
6800b57cec5SDimitry Andric{
6810b57cec5SDimitry Andric    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
6820b57cec5SDimitry Andric    {
6830b57cec5SDimitry Andric        __call_once_param<_Callable> __p(__func);
684*bdd1243dSDimitry Andric        std::__call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
6850b57cec5SDimitry Andric    }
6860b57cec5SDimitry Andric}
6870b57cec5SDimitry Andric
6880b57cec5SDimitry Andrictemplate<class _Callable>
6890b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
6900b57cec5SDimitry Andricvoid
6910b57cec5SDimitry Andriccall_once(once_flag& __flag, const _Callable& __func)
6920b57cec5SDimitry Andric{
6930b57cec5SDimitry Andric    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
6940b57cec5SDimitry Andric    {
6950b57cec5SDimitry Andric        __call_once_param<const _Callable> __p(__func);
696*bdd1243dSDimitry Andric        std::__call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
6970b57cec5SDimitry Andric    }
6980b57cec5SDimitry Andric}
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG
7010b57cec5SDimitry Andric
7020b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric_LIBCPP_POP_MACROS
7050b57cec5SDimitry Andric
706*bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
707*bdd1243dSDimitry Andric#  include <concepts>
708*bdd1243dSDimitry Andric#  include <functional>
709*bdd1243dSDimitry Andric#  include <type_traits>
710*bdd1243dSDimitry Andric#endif
711*bdd1243dSDimitry Andric
7120b57cec5SDimitry Andric#endif // _LIBCPP_MUTEX
713