xref: /llvm-project-15.0.7/libcxx/include/mutex (revision de4a57cb)
13e519524SHoward Hinnant// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
33e519524SHoward Hinnant//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73e519524SHoward Hinnant//
83e519524SHoward Hinnant//===----------------------------------------------------------------------===//
93e519524SHoward Hinnant
103e519524SHoward Hinnant#ifndef _LIBCPP_MUTEX
113e519524SHoward Hinnant#define _LIBCPP_MUTEX
123e519524SHoward Hinnant
133e519524SHoward Hinnant/*
143e519524SHoward Hinnant    mutex synopsis
153e519524SHoward Hinnant
163e519524SHoward Hinnantnamespace std
173e519524SHoward Hinnant{
183e519524SHoward Hinnant
193e519524SHoward Hinnantclass mutex
203e519524SHoward Hinnant{
213e519524SHoward Hinnantpublic:
2202e610efSHoward Hinnant     constexpr mutex() noexcept;
233e519524SHoward Hinnant     ~mutex();
243e519524SHoward Hinnant
253e519524SHoward Hinnant    mutex(const mutex&) = delete;
263e519524SHoward Hinnant    mutex& operator=(const mutex&) = delete;
273e519524SHoward Hinnant
283e519524SHoward Hinnant    void lock();
293e519524SHoward Hinnant    bool try_lock();
303e519524SHoward Hinnant    void unlock();
313e519524SHoward Hinnant
323e519524SHoward Hinnant    typedef pthread_mutex_t* native_handle_type;
333e519524SHoward Hinnant    native_handle_type native_handle();
343e519524SHoward Hinnant};
353e519524SHoward Hinnant
363e519524SHoward Hinnantclass recursive_mutex
373e519524SHoward Hinnant{
383e519524SHoward Hinnantpublic:
393e519524SHoward Hinnant     recursive_mutex();
403e519524SHoward Hinnant     ~recursive_mutex();
413e519524SHoward Hinnant
423e519524SHoward Hinnant    recursive_mutex(const recursive_mutex&) = delete;
433e519524SHoward Hinnant    recursive_mutex& operator=(const recursive_mutex&) = delete;
443e519524SHoward Hinnant
453e519524SHoward Hinnant    void lock();
4602e610efSHoward Hinnant    bool try_lock() noexcept;
473e519524SHoward Hinnant    void unlock();
483e519524SHoward Hinnant
493e519524SHoward Hinnant    typedef pthread_mutex_t* native_handle_type;
503e519524SHoward Hinnant    native_handle_type native_handle();
513e519524SHoward Hinnant};
523e519524SHoward Hinnant
533e519524SHoward Hinnantclass timed_mutex
543e519524SHoward Hinnant{
553e519524SHoward Hinnantpublic:
563e519524SHoward Hinnant     timed_mutex();
573e519524SHoward Hinnant     ~timed_mutex();
583e519524SHoward Hinnant
593e519524SHoward Hinnant    timed_mutex(const timed_mutex&) = delete;
603e519524SHoward Hinnant    timed_mutex& operator=(const timed_mutex&) = delete;
613e519524SHoward Hinnant
623e519524SHoward Hinnant    void lock();
633e519524SHoward Hinnant    bool try_lock();
643e519524SHoward Hinnant    template <class Rep, class Period>
653e519524SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
663e519524SHoward Hinnant    template <class Clock, class Duration>
673e519524SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
683e519524SHoward Hinnant    void unlock();
693e519524SHoward Hinnant};
703e519524SHoward Hinnant
713e519524SHoward Hinnantclass recursive_timed_mutex
723e519524SHoward Hinnant{
733e519524SHoward Hinnantpublic:
743e519524SHoward Hinnant     recursive_timed_mutex();
753e519524SHoward Hinnant     ~recursive_timed_mutex();
763e519524SHoward Hinnant
773e519524SHoward Hinnant    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
783e519524SHoward Hinnant    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
793e519524SHoward Hinnant
803e519524SHoward Hinnant    void lock();
8102e610efSHoward Hinnant    bool try_lock() noexcept;
823e519524SHoward Hinnant    template <class Rep, class Period>
833e519524SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
843e519524SHoward Hinnant    template <class Clock, class Duration>
853e519524SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
863e519524SHoward Hinnant    void unlock();
873e519524SHoward Hinnant};
883e519524SHoward Hinnant
89e16f2cb6SLouis Dionnestruct defer_lock_t { explicit defer_lock_t() = default; };
90e16f2cb6SLouis Dionnestruct try_to_lock_t { explicit try_to_lock_t() = default; };
91e16f2cb6SLouis Dionnestruct adopt_lock_t { explicit adopt_lock_t() = default; };
923e519524SHoward Hinnant
9340a01d53SMarshall Clowinline constexpr defer_lock_t  defer_lock{};
9440a01d53SMarshall Clowinline constexpr try_to_lock_t try_to_lock{};
9540a01d53SMarshall Clowinline constexpr adopt_lock_t  adopt_lock{};
963e519524SHoward Hinnant
973e519524SHoward Hinnanttemplate <class Mutex>
983e519524SHoward Hinnantclass lock_guard
993e519524SHoward Hinnant{
1003e519524SHoward Hinnantpublic:
1013e519524SHoward Hinnant    typedef Mutex mutex_type;
1023e519524SHoward Hinnant
1033e519524SHoward Hinnant    explicit lock_guard(mutex_type& m);
1043e519524SHoward Hinnant    lock_guard(mutex_type& m, adopt_lock_t);
1053e519524SHoward Hinnant    ~lock_guard();
1063e519524SHoward Hinnant
1073e519524SHoward Hinnant    lock_guard(lock_guard const&) = delete;
1083e519524SHoward Hinnant    lock_guard& operator=(lock_guard const&) = delete;
1093e519524SHoward Hinnant};
1103e519524SHoward Hinnant
1116015dd11SMarshall Clowtemplate <class... MutexTypes>
1126015dd11SMarshall Clowclass scoped_lock // C++17
11348f35e07SEric Fiselier{
11448f35e07SEric Fiselierpublic:
1157ad00511SJoe Loser    using mutex_type = Mutex;  // Only if sizeof...(MutexTypes) == 1
1166015dd11SMarshall Clow
1176015dd11SMarshall Clow    explicit scoped_lock(MutexTypes&... m);
11888c893ccSMarshall Clow    scoped_lock(adopt_lock_t, MutexTypes&... m);
1196015dd11SMarshall Clow    ~scoped_lock();
1206015dd11SMarshall Clow    scoped_lock(scoped_lock const&) = delete;
1216015dd11SMarshall Clow    scoped_lock& operator=(scoped_lock const&) = delete;
12248f35e07SEric Fiselierprivate:
12348f35e07SEric Fiselier    tuple<MutexTypes&...> pm; // exposition only
12448f35e07SEric Fiselier};
12548f35e07SEric Fiselier
1263e519524SHoward Hinnanttemplate <class Mutex>
1273e519524SHoward Hinnantclass unique_lock
1283e519524SHoward Hinnant{
1293e519524SHoward Hinnantpublic:
1303e519524SHoward Hinnant    typedef Mutex mutex_type;
13102e610efSHoward Hinnant    unique_lock() noexcept;
1323e519524SHoward Hinnant    explicit unique_lock(mutex_type& m);
13302e610efSHoward Hinnant    unique_lock(mutex_type& m, defer_lock_t) noexcept;
1343e519524SHoward Hinnant    unique_lock(mutex_type& m, try_to_lock_t);
1353e519524SHoward Hinnant    unique_lock(mutex_type& m, adopt_lock_t);
1363e519524SHoward Hinnant    template <class Clock, class Duration>
1373e519524SHoward Hinnant        unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
1383e519524SHoward Hinnant    template <class Rep, class Period>
1393e519524SHoward Hinnant        unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
1403e519524SHoward Hinnant    ~unique_lock();
1413e519524SHoward Hinnant
1423e519524SHoward Hinnant    unique_lock(unique_lock const&) = delete;
1433e519524SHoward Hinnant    unique_lock& operator=(unique_lock const&) = delete;
1443e519524SHoward Hinnant
14502e610efSHoward Hinnant    unique_lock(unique_lock&& u) noexcept;
14602e610efSHoward Hinnant    unique_lock& operator=(unique_lock&& u) noexcept;
1473e519524SHoward Hinnant
1483e519524SHoward Hinnant    void lock();
1493e519524SHoward Hinnant    bool try_lock();
1503e519524SHoward Hinnant
1513e519524SHoward Hinnant    template <class Rep, class Period>
1523e519524SHoward Hinnant        bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
1533e519524SHoward Hinnant    template <class Clock, class Duration>
1543e519524SHoward Hinnant        bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
1553e519524SHoward Hinnant
1563e519524SHoward Hinnant    void unlock();
1573e519524SHoward Hinnant
15802e610efSHoward Hinnant    void swap(unique_lock& u) noexcept;
15902e610efSHoward Hinnant    mutex_type* release() noexcept;
1603e519524SHoward Hinnant
16102e610efSHoward Hinnant    bool owns_lock() const noexcept;
16202e610efSHoward Hinnant    explicit operator bool () const noexcept;
16302e610efSHoward Hinnant    mutex_type* mutex() const noexcept;
1643e519524SHoward Hinnant};
1653e519524SHoward Hinnant
1663e519524SHoward Hinnanttemplate <class Mutex>
16702e610efSHoward Hinnant  void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
1683e519524SHoward Hinnant
1693e519524SHoward Hinnanttemplate <class L1, class L2, class... L3>
1703e519524SHoward Hinnant  int try_lock(L1&, L2&, L3&...);
1713e519524SHoward Hinnanttemplate <class L1, class L2, class... L3>
1723e519524SHoward Hinnant  void lock(L1&, L2&, L3&...);
1733e519524SHoward Hinnant
1743e519524SHoward Hinnantstruct once_flag
1753e519524SHoward Hinnant{
17602e610efSHoward Hinnant    constexpr once_flag() noexcept;
1773e519524SHoward Hinnant
1783e519524SHoward Hinnant    once_flag(const once_flag&) = delete;
1793e519524SHoward Hinnant    once_flag& operator=(const once_flag&) = delete;
1803e519524SHoward Hinnant};
1813e519524SHoward Hinnant
1823e519524SHoward Hinnanttemplate<class Callable, class ...Args>
1833e519524SHoward Hinnant  void call_once(once_flag& flag, Callable&& func, Args&&... args);
1843e519524SHoward Hinnant
1853e519524SHoward Hinnant}  // std
1863e519524SHoward Hinnant
1873e519524SHoward Hinnant*/
1883e519524SHoward Hinnant
189385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
1903e519524SHoward Hinnant#include <__config>
1913e519524SHoward Hinnant#include <__mutex_base>
192bfbd73f8SArthur O'Dwyer#include <__threading_support>
1936adbc83eSChristopher Di Bella#include <__utility/forward.h>
1940fd00a58SNico Weber#include <cstdint>
1951faf289eSEric Fiselier#include <memory>
196e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
197872a9116SHoward Hinnant# include <tuple>
198872a9116SHoward Hinnant#endif
199f56972e2SMarshall Clow#include <version>
2003e519524SHoward Hinnant
201*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
202*de4a57cbSLouis Dionne#  include <functional>
203*de4a57cbSLouis Dionne#endif
204*de4a57cbSLouis Dionne
205073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2063e519524SHoward Hinnant#  pragma GCC system_header
207073458b1SHoward Hinnant#endif
2083e519524SHoward Hinnant
209a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
210a016efb1SEric Fiselier#include <__undef_macros>
211a016efb1SEric Fiselier
212a016efb1SEric Fiselier
2133e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
2143e519524SHoward Hinnant
215b3fcc67fSJonathan Roelofs#ifndef _LIBCPP_HAS_NO_THREADS
216b3fcc67fSJonathan Roelofs
2176e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_mutex
2183e519524SHoward Hinnant{
21958a0dceeSSaleem Abdulrasool    __libcpp_recursive_mutex_t __m_;
2203e519524SHoward Hinnant
2213e519524SHoward Hinnantpublic:
2223e519524SHoward Hinnant    recursive_mutex();
2233e519524SHoward Hinnant    ~recursive_mutex();
2243e519524SHoward Hinnant
225feb80aa9SNikolas Klauser    recursive_mutex(const recursive_mutex&) = delete;
226feb80aa9SNikolas Klauser    recursive_mutex& operator=(const recursive_mutex&) = delete;
2273e519524SHoward Hinnant
2283e519524SHoward Hinnant    void lock();
22902e610efSHoward Hinnant    bool try_lock() _NOEXCEPT;
23002e610efSHoward Hinnant    void unlock()  _NOEXCEPT;
2313e519524SHoward Hinnant
23258a0dceeSSaleem Abdulrasool    typedef __libcpp_recursive_mutex_t* native_handle_type;
23358a0dceeSSaleem Abdulrasool
234392183f9SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
2353e519524SHoward Hinnant    native_handle_type native_handle() {return &__m_;}
2363e519524SHoward Hinnant};
2373e519524SHoward Hinnant
2386e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS timed_mutex
2393e519524SHoward Hinnant{
2403e519524SHoward Hinnant    mutex              __m_;
2413e519524SHoward Hinnant    condition_variable __cv_;
2423e519524SHoward Hinnant    bool               __locked_;
2433e519524SHoward Hinnantpublic:
2443e519524SHoward Hinnant     timed_mutex();
2453e519524SHoward Hinnant     ~timed_mutex();
2463e519524SHoward Hinnant
247feb80aa9SNikolas Klauser    timed_mutex(const timed_mutex&) = delete;
248feb80aa9SNikolas Klauser    timed_mutex& operator=(const timed_mutex&) = delete;
2493e519524SHoward Hinnant
2503e519524SHoward Hinnantpublic:
2513e519524SHoward Hinnant    void lock();
25202e610efSHoward Hinnant    bool try_lock() _NOEXCEPT;
2533e519524SHoward Hinnant    template <class _Rep, class _Period>
254392183f9SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
2553e519524SHoward Hinnant        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
2563dc6455fSHoward Hinnant            {return try_lock_until(chrono::steady_clock::now() + __d);}
2573e519524SHoward Hinnant    template <class _Clock, class _Duration>
258bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
2593e519524SHoward Hinnant        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
26002e610efSHoward Hinnant    void unlock() _NOEXCEPT;
2613e519524SHoward Hinnant};
2623e519524SHoward Hinnant
2633e519524SHoward Hinnanttemplate <class _Clock, class _Duration>
2643e519524SHoward Hinnantbool
2653e519524SHoward Hinnanttimed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
2663e519524SHoward Hinnant{
2673e519524SHoward Hinnant    using namespace chrono;
2683e519524SHoward Hinnant    unique_lock<mutex> __lk(__m_);
2693e519524SHoward Hinnant    bool no_timeout = _Clock::now() < __t;
2703e519524SHoward Hinnant    while (no_timeout && __locked_)
2713e519524SHoward Hinnant        no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout;
2723e519524SHoward Hinnant    if (!__locked_)
2733e519524SHoward Hinnant    {
2743e519524SHoward Hinnant        __locked_ = true;
2753e519524SHoward Hinnant        return true;
2763e519524SHoward Hinnant    }
2773e519524SHoward Hinnant    return false;
2783e519524SHoward Hinnant}
2793e519524SHoward Hinnant
2806e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS recursive_timed_mutex
2813e519524SHoward Hinnant{
2823e519524SHoward Hinnant    mutex              __m_;
2833e519524SHoward Hinnant    condition_variable __cv_;
2843e519524SHoward Hinnant    size_t             __count_;
2852b1d4254SMarshall Clow    __thread_id        __id_;
2863e519524SHoward Hinnantpublic:
2873e519524SHoward Hinnant    recursive_timed_mutex();
2883e519524SHoward Hinnant    ~recursive_timed_mutex();
2893e519524SHoward Hinnant
290feb80aa9SNikolas Klauser    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
291feb80aa9SNikolas Klauser    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
2923e519524SHoward Hinnant
2933e519524SHoward Hinnant    void lock();
29402e610efSHoward Hinnant    bool try_lock() _NOEXCEPT;
2953e519524SHoward Hinnant    template <class _Rep, class _Period>
296392183f9SHoward Hinnant        _LIBCPP_INLINE_VISIBILITY
2973e519524SHoward Hinnant        bool try_lock_for(const chrono::duration<_Rep, _Period>& __d)
2983dc6455fSHoward Hinnant            {return try_lock_until(chrono::steady_clock::now() + __d);}
2993e519524SHoward Hinnant    template <class _Clock, class _Duration>
300bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
3013e519524SHoward Hinnant        bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t);
30202e610efSHoward Hinnant    void unlock() _NOEXCEPT;
3033e519524SHoward Hinnant};
3043e519524SHoward Hinnant
3053e519524SHoward Hinnanttemplate <class _Clock, class _Duration>
3063e519524SHoward Hinnantbool
3073e519524SHoward Hinnantrecursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
3083e519524SHoward Hinnant{
3093e519524SHoward Hinnant    using namespace chrono;
3102b1d4254SMarshall Clow    __thread_id __id = this_thread::get_id();
3113e519524SHoward Hinnant    unique_lock<mutex> lk(__m_);
3122b1d4254SMarshall Clow    if (__id == __id_)
3133e519524SHoward Hinnant    {
3143e519524SHoward Hinnant        if (__count_ == numeric_limits<size_t>::max())
3153e519524SHoward Hinnant            return false;
3163e519524SHoward Hinnant        ++__count_;
3173e519524SHoward Hinnant        return true;
3183e519524SHoward Hinnant    }
3193e519524SHoward Hinnant    bool no_timeout = _Clock::now() < __t;
3203e519524SHoward Hinnant    while (no_timeout && __count_ != 0)
3213e519524SHoward Hinnant        no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout;
3223e519524SHoward Hinnant    if (__count_ == 0)
3233e519524SHoward Hinnant    {
3243e519524SHoward Hinnant        __count_ = 1;
3253e519524SHoward Hinnant        __id_ = __id;
3263e519524SHoward Hinnant        return true;
3273e519524SHoward Hinnant    }
3283e519524SHoward Hinnant    return false;
3293e519524SHoward Hinnant}
3303e519524SHoward Hinnant
3313e519524SHoward Hinnanttemplate <class _L0, class _L1>
3323e519524SHoward Hinnantint
3333e519524SHoward Hinnanttry_lock(_L0& __l0, _L1& __l1)
3343e519524SHoward Hinnant{
3353e519524SHoward Hinnant    unique_lock<_L0> __u0(__l0, try_to_lock);
3363e519524SHoward Hinnant    if (__u0.owns_lock())
3373e519524SHoward Hinnant    {
3383e519524SHoward Hinnant        if (__l1.try_lock())
3393e519524SHoward Hinnant        {
3403e519524SHoward Hinnant            __u0.release();
3413e519524SHoward Hinnant            return -1;
3423e519524SHoward Hinnant        }
3433e519524SHoward Hinnant        else
3443e519524SHoward Hinnant            return 1;
3453e519524SHoward Hinnant    }
3463e519524SHoward Hinnant    return 0;
3473e519524SHoward Hinnant}
3483e519524SHoward Hinnant
349e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
3503e519524SHoward Hinnant
3513e519524SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class... _L3>
3523e519524SHoward Hinnantint
3533e519524SHoward Hinnanttry_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3)
3543e519524SHoward Hinnant{
3553e519524SHoward Hinnant    int __r = 0;
3563e519524SHoward Hinnant    unique_lock<_L0> __u0(__l0, try_to_lock);
3573e519524SHoward Hinnant    if (__u0.owns_lock())
3583e519524SHoward Hinnant    {
3593e519524SHoward Hinnant        __r = try_lock(__l1, __l2, __l3...);
3603e519524SHoward Hinnant        if (__r == -1)
3613e519524SHoward Hinnant            __u0.release();
3623e519524SHoward Hinnant        else
3633e519524SHoward Hinnant            ++__r;
3643e519524SHoward Hinnant    }
3653e519524SHoward Hinnant    return __r;
3663e519524SHoward Hinnant}
3673e519524SHoward Hinnant
368e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
3693e519524SHoward Hinnant
3703e519524SHoward Hinnanttemplate <class _L0, class _L1>
3713e519524SHoward Hinnantvoid
3723e519524SHoward Hinnantlock(_L0& __l0, _L1& __l1)
3733e519524SHoward Hinnant{
3743e519524SHoward Hinnant    while (true)
3753e519524SHoward Hinnant    {
3763e519524SHoward Hinnant        {
3773e519524SHoward Hinnant            unique_lock<_L0> __u0(__l0);
3783e519524SHoward Hinnant            if (__l1.try_lock())
3793e519524SHoward Hinnant            {
3803e519524SHoward Hinnant                __u0.release();
3813e519524SHoward Hinnant                break;
3823e519524SHoward Hinnant            }
3833e519524SHoward Hinnant        }
384c7e4239fSAsiri Rathnayake        __libcpp_thread_yield();
3853e519524SHoward Hinnant        {
3863e519524SHoward Hinnant            unique_lock<_L1> __u1(__l1);
3873e519524SHoward Hinnant            if (__l0.try_lock())
3883e519524SHoward Hinnant            {
3893e519524SHoward Hinnant                __u1.release();
3903e519524SHoward Hinnant                break;
3913e519524SHoward Hinnant            }
3923e519524SHoward Hinnant        }
393c7e4239fSAsiri Rathnayake        __libcpp_thread_yield();
3943e519524SHoward Hinnant    }
3953e519524SHoward Hinnant}
3963e519524SHoward Hinnant
397e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
3983e519524SHoward Hinnant
39959a7dc95SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class ..._L3>
4003e519524SHoward Hinnantvoid
40159a7dc95SHoward Hinnant__lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
4023e519524SHoward Hinnant{
4033e519524SHoward Hinnant    while (true)
4043e519524SHoward Hinnant    {
4053e519524SHoward Hinnant        switch (__i)
4063e519524SHoward Hinnant        {
4073e519524SHoward Hinnant        case 0:
4083e519524SHoward Hinnant            {
4093e519524SHoward Hinnant                unique_lock<_L0> __u0(__l0);
41059a7dc95SHoward Hinnant                __i = try_lock(__l1, __l2, __l3...);
4113e519524SHoward Hinnant                if (__i == -1)
4123e519524SHoward Hinnant                {
4133e519524SHoward Hinnant                    __u0.release();
4143e519524SHoward Hinnant                    return;
4153e519524SHoward Hinnant                }
4163e519524SHoward Hinnant            }
4173e519524SHoward Hinnant            ++__i;
418c7e4239fSAsiri Rathnayake            __libcpp_thread_yield();
4193e519524SHoward Hinnant            break;
4203e519524SHoward Hinnant        case 1:
4213e519524SHoward Hinnant            {
4223e519524SHoward Hinnant                unique_lock<_L1> __u1(__l1);
42359a7dc95SHoward Hinnant                __i = try_lock(__l2, __l3..., __l0);
4243e519524SHoward Hinnant                if (__i == -1)
4253e519524SHoward Hinnant                {
4263e519524SHoward Hinnant                    __u1.release();
4273e519524SHoward Hinnant                    return;
4283e519524SHoward Hinnant                }
4293e519524SHoward Hinnant            }
43059a7dc95SHoward Hinnant            if (__i == sizeof...(_L3) + 1)
4313e519524SHoward Hinnant                __i = 0;
4323e519524SHoward Hinnant            else
4333e519524SHoward Hinnant                __i += 2;
434c7e4239fSAsiri Rathnayake            __libcpp_thread_yield();
4353e519524SHoward Hinnant            break;
4363e519524SHoward Hinnant        default:
43759a7dc95SHoward Hinnant            __lock_first(__i - 2, __l2, __l3..., __l0, __l1);
4383e519524SHoward Hinnant            return;
4393e519524SHoward Hinnant        }
4403e519524SHoward Hinnant    }
4413e519524SHoward Hinnant}
4423e519524SHoward Hinnant
44359a7dc95SHoward Hinnanttemplate <class _L0, class _L1, class _L2, class ..._L3>
444392183f9SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
4453e519524SHoward Hinnantvoid
44659a7dc95SHoward Hinnantlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3)
4473e519524SHoward Hinnant{
44859a7dc95SHoward Hinnant    __lock_first(0, __l0, __l1, __l2, __l3...);
4493e519524SHoward Hinnant}
4503e519524SHoward Hinnant
45148f35e07SEric Fiseliertemplate <class _L0>
45248f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
45348f35e07SEric Fiseliervoid __unlock(_L0& __l0) {
45448f35e07SEric Fiselier    __l0.unlock();
45548f35e07SEric Fiselier}
45648f35e07SEric Fiselier
45748f35e07SEric Fiseliertemplate <class _L0, class _L1>
45848f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
45948f35e07SEric Fiseliervoid __unlock(_L0& __l0, _L1& __l1) {
46048f35e07SEric Fiselier    __l0.unlock();
46148f35e07SEric Fiselier    __l1.unlock();
46248f35e07SEric Fiselier}
46348f35e07SEric Fiselier
46448f35e07SEric Fiseliertemplate <class _L0, class _L1, class _L2, class ..._L3>
46548f35e07SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
46648f35e07SEric Fiseliervoid __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) {
46748f35e07SEric Fiselier    __l0.unlock();
46848f35e07SEric Fiselier    __l1.unlock();
46948f35e07SEric Fiselier    _VSTD::__unlock(__l2, __l3...);
47048f35e07SEric Fiselier}
47148f35e07SEric Fiselier
472e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
4733e519524SHoward Hinnant
4749f3fd40aSMarshall Clow#if _LIBCPP_STD_VER > 14
4759f3fd40aSMarshall Clowtemplate <class ..._Mutexes>
4769f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock;
4779f3fd40aSMarshall Clow
4789f3fd40aSMarshall Clowtemplate <>
4799f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock<> {
4809f3fd40aSMarshall Clowpublic:
4819f3fd40aSMarshall Clow    explicit scoped_lock() {}
4829f3fd40aSMarshall Clow    ~scoped_lock() = default;
4839f3fd40aSMarshall Clow
4849f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
4859f3fd40aSMarshall Clow    explicit scoped_lock(adopt_lock_t) {}
4869f3fd40aSMarshall Clow
4879f3fd40aSMarshall Clow    scoped_lock(scoped_lock const&) = delete;
4889f3fd40aSMarshall Clow    scoped_lock& operator=(scoped_lock const&) = delete;
4899f3fd40aSMarshall Clow};
4909f3fd40aSMarshall Clow
4919f3fd40aSMarshall Clowtemplate <class _Mutex>
4927f208f02SAaron Puchertclass _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
4939f3fd40aSMarshall Clowpublic:
4949f3fd40aSMarshall Clow    typedef _Mutex  mutex_type;
4959f3fd40aSMarshall Clowprivate:
4969f3fd40aSMarshall Clow    mutex_type& __m_;
4979f3fd40aSMarshall Clowpublic:
4989f3fd40aSMarshall Clow    explicit scoped_lock(mutex_type & __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
4999f3fd40aSMarshall Clow        : __m_(__m) {__m_.lock();}
5009f3fd40aSMarshall Clow
5019f3fd40aSMarshall Clow    ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();}
5029f3fd40aSMarshall Clow
5039f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
50488c893ccSMarshall Clow    explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
5059f3fd40aSMarshall Clow        : __m_(__m) {}
5069f3fd40aSMarshall Clow
5079f3fd40aSMarshall Clow    scoped_lock(scoped_lock const&) = delete;
5089f3fd40aSMarshall Clow    scoped_lock& operator=(scoped_lock const&) = delete;
5099f3fd40aSMarshall Clow};
5109f3fd40aSMarshall Clow
5119f3fd40aSMarshall Clowtemplate <class ..._MArgs>
5129f3fd40aSMarshall Clowclass _LIBCPP_TEMPLATE_VIS scoped_lock
5139f3fd40aSMarshall Clow{
5149f3fd40aSMarshall Clow    static_assert(sizeof...(_MArgs) > 1, "At least 2 lock types required");
5159f3fd40aSMarshall Clow    typedef tuple<_MArgs&...> _MutexTuple;
5169f3fd40aSMarshall Clow
5179f3fd40aSMarshall Clowpublic:
5189f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
5199f3fd40aSMarshall Clow    explicit scoped_lock(_MArgs&... __margs)
5209f3fd40aSMarshall Clow      : __t_(__margs...)
5219f3fd40aSMarshall Clow    {
5229f3fd40aSMarshall Clow        _VSTD::lock(__margs...);
5239f3fd40aSMarshall Clow    }
5249f3fd40aSMarshall Clow
5259f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
52688c893ccSMarshall Clow    scoped_lock(adopt_lock_t, _MArgs&... __margs)
5279f3fd40aSMarshall Clow        : __t_(__margs...)
5289f3fd40aSMarshall Clow    {
5299f3fd40aSMarshall Clow    }
5309f3fd40aSMarshall Clow
5319f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
5329f3fd40aSMarshall Clow    ~scoped_lock() {
5339f3fd40aSMarshall Clow        typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices;
5349f3fd40aSMarshall Clow        __unlock_unpack(_Indices{}, __t_);
5359f3fd40aSMarshall Clow    }
5369f3fd40aSMarshall Clow
5379f3fd40aSMarshall Clow    scoped_lock(scoped_lock const&) = delete;
5389f3fd40aSMarshall Clow    scoped_lock& operator=(scoped_lock const&) = delete;
5399f3fd40aSMarshall Clow
5409f3fd40aSMarshall Clowprivate:
5419f3fd40aSMarshall Clow    template <size_t ..._Indx>
5429f3fd40aSMarshall Clow    _LIBCPP_INLINE_VISIBILITY
5439f3fd40aSMarshall Clow    static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) {
5449f3fd40aSMarshall Clow        _VSTD::__unlock(_VSTD::get<_Indx>(__mt)...);
5459f3fd40aSMarshall Clow    }
5469f3fd40aSMarshall Clow
5479f3fd40aSMarshall Clow    _MutexTuple __t_;
5489f3fd40aSMarshall Clow};
5499f3fd40aSMarshall Clow
5509f3fd40aSMarshall Clow#endif // _LIBCPP_STD_VER > 14
551b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS
552b3fcc67fSJonathan Roelofs
553e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS once_flag;
5543e519524SHoward Hinnant
555e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
5563e519524SHoward Hinnant
5573e519524SHoward Hinnanttemplate<class _Callable, class... _Args>
558aeb85680SHoward Hinnant_LIBCPP_INLINE_VISIBILITY
5593e519524SHoward Hinnantvoid call_once(once_flag&, _Callable&&, _Args&&...);
5603e519524SHoward Hinnant
561e11fb13bSEric Fiselier#else  // _LIBCPP_CXX03_LANG
5623e519524SHoward Hinnant
5633e519524SHoward Hinnanttemplate<class _Callable>
564aeb85680SHoward Hinnant_LIBCPP_INLINE_VISIBILITY
565793f59e7SEric Fiseliervoid call_once(once_flag&, _Callable&);
566793f59e7SEric Fiselier
567793f59e7SEric Fiseliertemplate<class _Callable>
568793f59e7SEric Fiselier_LIBCPP_INLINE_VISIBILITY
569793f59e7SEric Fiseliervoid call_once(once_flag&, const _Callable&);
5703e519524SHoward Hinnant
571e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
5723e519524SHoward Hinnant
573e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS once_flag
5743e519524SHoward Hinnant{
575392183f9SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
57602e610efSHoward Hinnant    _LIBCPP_CONSTEXPR
57702e610efSHoward Hinnant        once_flag() _NOEXCEPT : __state_(0) {}
578feb80aa9SNikolas Klauser    once_flag(const once_flag&) = delete;
579feb80aa9SNikolas Klauser    once_flag& operator=(const once_flag&) = delete;
5803e519524SHoward Hinnant
5810fd00a58SNico Weber#if defined(_LIBCPP_ABI_MICROSOFT)
5820fd00a58SNico Weber   typedef uintptr_t _State_type;
5830fd00a58SNico Weber#else
5840fd00a58SNico Weber   typedef unsigned long _State_type;
5850fd00a58SNico Weber#endif
5860fd00a58SNico Weber
5873e519524SHoward Hinnantprivate:
5880fd00a58SNico Weber    _State_type __state_;
5893e519524SHoward Hinnant
590e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
5913e519524SHoward Hinnant    template<class _Callable, class... _Args>
5923e519524SHoward Hinnant    friend
5933e519524SHoward Hinnant    void call_once(once_flag&, _Callable&&, _Args&&...);
594e11fb13bSEric Fiselier#else  // _LIBCPP_CXX03_LANG
5953e519524SHoward Hinnant    template<class _Callable>
5963e519524SHoward Hinnant    friend
597793f59e7SEric Fiselier    void call_once(once_flag&, _Callable&);
598793f59e7SEric Fiselier
599793f59e7SEric Fiselier    template<class _Callable>
600793f59e7SEric Fiselier    friend
601793f59e7SEric Fiselier    void call_once(once_flag&, const _Callable&);
602e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
6033e519524SHoward Hinnant};
6043e519524SHoward Hinnant
605e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
606872a9116SHoward Hinnant
607c003db1fSHoward Hinnanttemplate <class _Fp>
608872a9116SHoward Hinnantclass __call_once_param
609872a9116SHoward Hinnant{
610793f59e7SEric Fiselier    _Fp& __f_;
611872a9116SHoward Hinnantpublic:
612872a9116SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
613793f59e7SEric Fiselier    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
614872a9116SHoward Hinnant
615872a9116SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
616872a9116SHoward Hinnant    void operator()()
617872a9116SHoward Hinnant    {
618c003db1fSHoward Hinnant        typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index;
619872a9116SHoward Hinnant        __execute(_Index());
620872a9116SHoward Hinnant    }
621872a9116SHoward Hinnant
622872a9116SHoward Hinnantprivate:
623872a9116SHoward Hinnant    template <size_t ..._Indices>
624872a9116SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
625872a9116SHoward Hinnant    void __execute(__tuple_indices<_Indices...>)
626872a9116SHoward Hinnant    {
627781c476cSArthur O'Dwyer        _VSTD::__invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
628872a9116SHoward Hinnant    }
629872a9116SHoward Hinnant};
630872a9116SHoward Hinnant
631872a9116SHoward Hinnant#else
632872a9116SHoward Hinnant
633c003db1fSHoward Hinnanttemplate <class _Fp>
6343e519524SHoward Hinnantclass __call_once_param
6353e519524SHoward Hinnant{
636793f59e7SEric Fiselier    _Fp& __f_;
6373e519524SHoward Hinnantpublic:
638392183f9SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
639793f59e7SEric Fiselier    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
6403e519524SHoward Hinnant
641392183f9SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
6423e519524SHoward Hinnant    void operator()()
6433e519524SHoward Hinnant    {
6443e519524SHoward Hinnant        __f_();
6453e519524SHoward Hinnant    }
6463e519524SHoward Hinnant};
6473e519524SHoward Hinnant
648872a9116SHoward Hinnant#endif
649872a9116SHoward Hinnant
650c003db1fSHoward Hinnanttemplate <class _Fp>
65148b7068bSLouis Dionnevoid _LIBCPP_INLINE_VISIBILITY
6523e519524SHoward Hinnant__call_once_proxy(void* __vp)
6533e519524SHoward Hinnant{
654c003db1fSHoward Hinnant    __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);
6553e519524SHoward Hinnant    (*__p)();
6563e519524SHoward Hinnant}
6573e519524SHoward Hinnant
6580fd00a58SNico Weber_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*,
6590fd00a58SNico Weber                                  void (*)(void*));
6603e519524SHoward Hinnant
661e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
6623e519524SHoward Hinnant
6633e519524SHoward Hinnanttemplate<class _Callable, class... _Args>
6643e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
6653e519524SHoward Hinnantvoid
6663e519524SHoward Hinnantcall_once(once_flag& __flag, _Callable&& __func, _Args&&... __args)
6673e519524SHoward Hinnant{
6680fd00a58SNico Weber    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
6693e519524SHoward Hinnant    {
670793f59e7SEric Fiselier        typedef tuple<_Callable&&, _Args&&...> _Gp;
671793f59e7SEric Fiselier        _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
672793f59e7SEric Fiselier        __call_once_param<_Gp> __p(__f);
673c003db1fSHoward Hinnant        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
6743e519524SHoward Hinnant    }
6753e519524SHoward Hinnant}
6763e519524SHoward Hinnant
677e11fb13bSEric Fiselier#else  // _LIBCPP_CXX03_LANG
6783e519524SHoward Hinnant
6793e519524SHoward Hinnanttemplate<class _Callable>
6803e519524SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
6813e519524SHoward Hinnantvoid
682793f59e7SEric Fiseliercall_once(once_flag& __flag, _Callable& __func)
6833e519524SHoward Hinnant{
6840fd00a58SNico Weber    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
6853e519524SHoward Hinnant    {
6863e519524SHoward Hinnant        __call_once_param<_Callable> __p(__func);
6873e519524SHoward Hinnant        __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>);
6883e519524SHoward Hinnant    }
6893e519524SHoward Hinnant}
6903e519524SHoward Hinnant
691793f59e7SEric Fiseliertemplate<class _Callable>
692793f59e7SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
693793f59e7SEric Fiseliervoid
694793f59e7SEric Fiseliercall_once(once_flag& __flag, const _Callable& __func)
695793f59e7SEric Fiselier{
6960fd00a58SNico Weber    if (__libcpp_acquire_load(&__flag.__state_) != ~once_flag::_State_type(0))
697793f59e7SEric Fiselier    {
698793f59e7SEric Fiselier        __call_once_param<const _Callable> __p(__func);
699793f59e7SEric Fiselier        __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
700793f59e7SEric Fiselier    }
701793f59e7SEric Fiselier}
702793f59e7SEric Fiselier
703e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
7043e519524SHoward Hinnant
7053e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
7063e519524SHoward Hinnant
707a016efb1SEric Fiselier_LIBCPP_POP_MACROS
708a016efb1SEric Fiselier
7093e519524SHoward Hinnant#endif // _LIBCPP_MUTEX
710