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