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