xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/thread (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg// -*- C++ -*-
2*4d6fc14bSjoerg//===--------------------------- thread -----------------------------------===//
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_THREAD
11*4d6fc14bSjoerg#define _LIBCPP_THREAD
12*4d6fc14bSjoerg
13*4d6fc14bSjoerg/*
14*4d6fc14bSjoerg
15*4d6fc14bSjoerg    thread synopsis
16*4d6fc14bSjoerg
17*4d6fc14bSjoergnamespace std
18*4d6fc14bSjoerg{
19*4d6fc14bSjoerg
20*4d6fc14bSjoergclass thread
21*4d6fc14bSjoerg{
22*4d6fc14bSjoergpublic:
23*4d6fc14bSjoerg    class id;
24*4d6fc14bSjoerg    typedef pthread_t native_handle_type;
25*4d6fc14bSjoerg
26*4d6fc14bSjoerg    thread() noexcept;
27*4d6fc14bSjoerg    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
28*4d6fc14bSjoerg    ~thread();
29*4d6fc14bSjoerg
30*4d6fc14bSjoerg    thread(const thread&) = delete;
31*4d6fc14bSjoerg    thread(thread&& t) noexcept;
32*4d6fc14bSjoerg
33*4d6fc14bSjoerg    thread& operator=(const thread&) = delete;
34*4d6fc14bSjoerg    thread& operator=(thread&& t) noexcept;
35*4d6fc14bSjoerg
36*4d6fc14bSjoerg    void swap(thread& t) noexcept;
37*4d6fc14bSjoerg
38*4d6fc14bSjoerg    bool joinable() const noexcept;
39*4d6fc14bSjoerg    void join();
40*4d6fc14bSjoerg    void detach();
41*4d6fc14bSjoerg    id get_id() const noexcept;
42*4d6fc14bSjoerg    native_handle_type native_handle();
43*4d6fc14bSjoerg
44*4d6fc14bSjoerg    static unsigned hardware_concurrency() noexcept;
45*4d6fc14bSjoerg};
46*4d6fc14bSjoerg
47*4d6fc14bSjoergvoid swap(thread& x, thread& y) noexcept;
48*4d6fc14bSjoerg
49*4d6fc14bSjoergclass thread::id
50*4d6fc14bSjoerg{
51*4d6fc14bSjoergpublic:
52*4d6fc14bSjoerg    id() noexcept;
53*4d6fc14bSjoerg};
54*4d6fc14bSjoerg
55*4d6fc14bSjoergbool operator==(thread::id x, thread::id y) noexcept;
56*4d6fc14bSjoergbool operator!=(thread::id x, thread::id y) noexcept;
57*4d6fc14bSjoergbool operator< (thread::id x, thread::id y) noexcept;
58*4d6fc14bSjoergbool operator<=(thread::id x, thread::id y) noexcept;
59*4d6fc14bSjoergbool operator> (thread::id x, thread::id y) noexcept;
60*4d6fc14bSjoergbool operator>=(thread::id x, thread::id y) noexcept;
61*4d6fc14bSjoerg
62*4d6fc14bSjoergtemplate<class charT, class traits>
63*4d6fc14bSjoergbasic_ostream<charT, traits>&
64*4d6fc14bSjoergoperator<<(basic_ostream<charT, traits>& out, thread::id id);
65*4d6fc14bSjoerg
66*4d6fc14bSjoergnamespace this_thread
67*4d6fc14bSjoerg{
68*4d6fc14bSjoerg
69*4d6fc14bSjoergthread::id get_id() noexcept;
70*4d6fc14bSjoerg
71*4d6fc14bSjoergvoid yield() noexcept;
72*4d6fc14bSjoerg
73*4d6fc14bSjoergtemplate <class Clock, class Duration>
74*4d6fc14bSjoergvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
75*4d6fc14bSjoerg
76*4d6fc14bSjoergtemplate <class Rep, class Period>
77*4d6fc14bSjoergvoid sleep_for(const chrono::duration<Rep, Period>& rel_time);
78*4d6fc14bSjoerg
79*4d6fc14bSjoerg}  // this_thread
80*4d6fc14bSjoerg
81*4d6fc14bSjoerg}  // std
82*4d6fc14bSjoerg
83*4d6fc14bSjoerg*/
84*4d6fc14bSjoerg
85*4d6fc14bSjoerg#include <__config>
86*4d6fc14bSjoerg#include <iosfwd>
87*4d6fc14bSjoerg#include <__functional_base>
88*4d6fc14bSjoerg#include <type_traits>
89*4d6fc14bSjoerg#include <cstddef>
90*4d6fc14bSjoerg#include <functional>
91*4d6fc14bSjoerg#include <memory>
92*4d6fc14bSjoerg#include <system_error>
93*4d6fc14bSjoerg#include <chrono>
94*4d6fc14bSjoerg#include <__mutex_base>
95*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG
96*4d6fc14bSjoerg#include <tuple>
97*4d6fc14bSjoerg#endif
98*4d6fc14bSjoerg#include <__threading_support>
99*4d6fc14bSjoerg#include <__debug>
100*4d6fc14bSjoerg
101*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
102*4d6fc14bSjoerg#pragma GCC system_header
103*4d6fc14bSjoerg#endif
104*4d6fc14bSjoerg
105*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS
106*4d6fc14bSjoerg#include <__undef_macros>
107*4d6fc14bSjoerg
108*4d6fc14bSjoerg#ifdef _LIBCPP_HAS_NO_THREADS
109*4d6fc14bSjoerg#error <thread> is not supported on this single threaded system
110*4d6fc14bSjoerg#else // !_LIBCPP_HAS_NO_THREADS
111*4d6fc14bSjoerg
112*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD
113*4d6fc14bSjoerg
114*4d6fc14bSjoergtemplate <class _Tp> class __thread_specific_ptr;
115*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS __thread_struct;
116*4d6fc14bSjoergclass _LIBCPP_HIDDEN __thread_struct_imp;
117*4d6fc14bSjoergclass __assoc_sub_state;
118*4d6fc14bSjoerg
119*4d6fc14bSjoerg_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
120*4d6fc14bSjoerg
121*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS __thread_struct
122*4d6fc14bSjoerg{
123*4d6fc14bSjoerg    __thread_struct_imp* __p_;
124*4d6fc14bSjoerg
125*4d6fc14bSjoerg    __thread_struct(const __thread_struct&);
126*4d6fc14bSjoerg    __thread_struct& operator=(const __thread_struct&);
127*4d6fc14bSjoergpublic:
128*4d6fc14bSjoerg    __thread_struct();
129*4d6fc14bSjoerg    ~__thread_struct();
130*4d6fc14bSjoerg
131*4d6fc14bSjoerg    void notify_all_at_thread_exit(condition_variable*, mutex*);
132*4d6fc14bSjoerg    void __make_ready_at_thread_exit(__assoc_sub_state*);
133*4d6fc14bSjoerg};
134*4d6fc14bSjoerg
135*4d6fc14bSjoergtemplate <class _Tp>
136*4d6fc14bSjoergclass __thread_specific_ptr
137*4d6fc14bSjoerg{
138*4d6fc14bSjoerg    __libcpp_tls_key __key_;
139*4d6fc14bSjoerg
140*4d6fc14bSjoerg     // Only __thread_local_data() may construct a __thread_specific_ptr
141*4d6fc14bSjoerg     // and only with _Tp == __thread_struct.
142*4d6fc14bSjoerg    static_assert((is_same<_Tp, __thread_struct>::value), "");
143*4d6fc14bSjoerg    __thread_specific_ptr();
144*4d6fc14bSjoerg    friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
145*4d6fc14bSjoerg
146*4d6fc14bSjoerg    __thread_specific_ptr(const __thread_specific_ptr&);
147*4d6fc14bSjoerg    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
148*4d6fc14bSjoerg
149*4d6fc14bSjoerg    _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
150*4d6fc14bSjoerg
151*4d6fc14bSjoergpublic:
152*4d6fc14bSjoerg    typedef _Tp* pointer;
153*4d6fc14bSjoerg
154*4d6fc14bSjoerg    ~__thread_specific_ptr();
155*4d6fc14bSjoerg
156*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
157*4d6fc14bSjoerg    pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));}
158*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
159*4d6fc14bSjoerg    pointer operator*() const {return *get();}
160*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
161*4d6fc14bSjoerg    pointer operator->() const {return get();}
162*4d6fc14bSjoerg    void set_pointer(pointer __p);
163*4d6fc14bSjoerg};
164*4d6fc14bSjoerg
165*4d6fc14bSjoergtemplate <class _Tp>
166*4d6fc14bSjoergvoid _LIBCPP_TLS_DESTRUCTOR_CC
167*4d6fc14bSjoerg__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
168*4d6fc14bSjoerg{
169*4d6fc14bSjoerg    delete static_cast<pointer>(__p);
170*4d6fc14bSjoerg}
171*4d6fc14bSjoerg
172*4d6fc14bSjoergtemplate <class _Tp>
173*4d6fc14bSjoerg__thread_specific_ptr<_Tp>::__thread_specific_ptr()
174*4d6fc14bSjoerg{
175*4d6fc14bSjoerg  int __ec =
176*4d6fc14bSjoerg      __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
177*4d6fc14bSjoerg  if (__ec)
178*4d6fc14bSjoerg    __throw_system_error(__ec, "__thread_specific_ptr construction failed");
179*4d6fc14bSjoerg}
180*4d6fc14bSjoerg
181*4d6fc14bSjoergtemplate <class _Tp>
182*4d6fc14bSjoerg__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
183*4d6fc14bSjoerg{
184*4d6fc14bSjoerg    // __thread_specific_ptr is only created with a static storage duration
185*4d6fc14bSjoerg    // so this destructor is only invoked during program termination. Invoking
186*4d6fc14bSjoerg    // pthread_key_delete(__key_) may prevent other threads from deleting their
187*4d6fc14bSjoerg    // thread local data. For this reason we leak the key.
188*4d6fc14bSjoerg}
189*4d6fc14bSjoerg
190*4d6fc14bSjoergtemplate <class _Tp>
191*4d6fc14bSjoergvoid
192*4d6fc14bSjoerg__thread_specific_ptr<_Tp>::set_pointer(pointer __p)
193*4d6fc14bSjoerg{
194*4d6fc14bSjoerg    _LIBCPP_ASSERT(get() == nullptr,
195*4d6fc14bSjoerg                   "Attempting to overwrite thread local data");
196*4d6fc14bSjoerg    __libcpp_tls_set(__key_, __p);
197*4d6fc14bSjoerg}
198*4d6fc14bSjoerg
199*4d6fc14bSjoergtemplate<>
200*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
201*4d6fc14bSjoerg    : public unary_function<__thread_id, size_t>
202*4d6fc14bSjoerg{
203*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
204*4d6fc14bSjoerg    size_t operator()(__thread_id __v) const _NOEXCEPT
205*4d6fc14bSjoerg    {
206*4d6fc14bSjoerg        return hash<__libcpp_thread_id>()(__v.__id_);
207*4d6fc14bSjoerg    }
208*4d6fc14bSjoerg};
209*4d6fc14bSjoerg
210*4d6fc14bSjoergtemplate<class _CharT, class _Traits>
211*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY
212*4d6fc14bSjoergbasic_ostream<_CharT, _Traits>&
213*4d6fc14bSjoergoperator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
214*4d6fc14bSjoerg{return __os << __id.__id_;}
215*4d6fc14bSjoerg
216*4d6fc14bSjoergclass _LIBCPP_TYPE_VIS thread
217*4d6fc14bSjoerg{
218*4d6fc14bSjoerg    __libcpp_thread_t __t_;
219*4d6fc14bSjoerg
220*4d6fc14bSjoerg    thread(const thread&);
221*4d6fc14bSjoerg    thread& operator=(const thread&);
222*4d6fc14bSjoergpublic:
223*4d6fc14bSjoerg    typedef __thread_id id;
224*4d6fc14bSjoerg    typedef __libcpp_thread_t native_handle_type;
225*4d6fc14bSjoerg
226*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
227*4d6fc14bSjoerg    thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
228*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG
229*4d6fc14bSjoerg    template <class _Fp, class ..._Args,
230*4d6fc14bSjoerg              class = typename enable_if
231*4d6fc14bSjoerg              <
232*4d6fc14bSjoerg                   !is_same<typename __uncvref<_Fp>::type, thread>::value
233*4d6fc14bSjoerg              >::type
234*4d6fc14bSjoerg             >
235*4d6fc14bSjoerg        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
236*4d6fc14bSjoerg        explicit thread(_Fp&& __f, _Args&&... __args);
237*4d6fc14bSjoerg#else  // _LIBCPP_CXX03_LANG
238*4d6fc14bSjoerg    template <class _Fp>
239*4d6fc14bSjoerg    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
240*4d6fc14bSjoerg    explicit thread(_Fp __f);
241*4d6fc14bSjoerg#endif
242*4d6fc14bSjoerg    ~thread();
243*4d6fc14bSjoerg
244*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
245*4d6fc14bSjoerg    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {
246*4d6fc14bSjoerg        __t.__t_ = _LIBCPP_NULL_THREAD;
247*4d6fc14bSjoerg    }
248*4d6fc14bSjoerg
249*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
250*4d6fc14bSjoerg    thread& operator=(thread&& __t) _NOEXCEPT {
251*4d6fc14bSjoerg        if (!__libcpp_thread_isnull(&__t_))
252*4d6fc14bSjoerg            terminate();
253*4d6fc14bSjoerg        __t_ = __t.__t_;
254*4d6fc14bSjoerg        __t.__t_ = _LIBCPP_NULL_THREAD;
255*4d6fc14bSjoerg        return *this;
256*4d6fc14bSjoerg    }
257*4d6fc14bSjoerg
258*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
259*4d6fc14bSjoerg    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
260*4d6fc14bSjoerg
261*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
262*4d6fc14bSjoerg    bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);}
263*4d6fc14bSjoerg    void join();
264*4d6fc14bSjoerg    void detach();
265*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
266*4d6fc14bSjoerg    id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);}
267*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
268*4d6fc14bSjoerg    native_handle_type native_handle() _NOEXCEPT {return __t_;}
269*4d6fc14bSjoerg
270*4d6fc14bSjoerg    static unsigned hardware_concurrency() _NOEXCEPT;
271*4d6fc14bSjoerg};
272*4d6fc14bSjoerg
273*4d6fc14bSjoerg#ifndef _LIBCPP_CXX03_LANG
274*4d6fc14bSjoerg
275*4d6fc14bSjoergtemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices>
276*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
277*4d6fc14bSjoergvoid
278*4d6fc14bSjoerg__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>)
279*4d6fc14bSjoerg{
280*4d6fc14bSjoerg    _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
281*4d6fc14bSjoerg}
282*4d6fc14bSjoerg
283*4d6fc14bSjoergtemplate <class _Fp>
284*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY
285*4d6fc14bSjoergvoid* __thread_proxy(void* __vp)
286*4d6fc14bSjoerg{
287*4d6fc14bSjoerg    // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...>
288*4d6fc14bSjoerg    unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
289*4d6fc14bSjoerg    __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release());
290*4d6fc14bSjoerg    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
291*4d6fc14bSjoerg    _VSTD::__thread_execute(*__p.get(), _Index());
292*4d6fc14bSjoerg    return nullptr;
293*4d6fc14bSjoerg}
294*4d6fc14bSjoerg
295*4d6fc14bSjoergtemplate <class _Fp, class ..._Args,
296*4d6fc14bSjoerg          class
297*4d6fc14bSjoerg         >
298*4d6fc14bSjoergthread::thread(_Fp&& __f, _Args&&... __args)
299*4d6fc14bSjoerg{
300*4d6fc14bSjoerg    typedef unique_ptr<__thread_struct> _TSPtr;
301*4d6fc14bSjoerg    _TSPtr __tsp(new __thread_struct);
302*4d6fc14bSjoerg    typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
303*4d6fc14bSjoerg    unique_ptr<_Gp> __p(
304*4d6fc14bSjoerg            new _Gp(_VSTD::move(__tsp),
305*4d6fc14bSjoerg                    _VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
306*4d6fc14bSjoerg                    _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
307*4d6fc14bSjoerg    int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
308*4d6fc14bSjoerg    if (__ec == 0)
309*4d6fc14bSjoerg        __p.release();
310*4d6fc14bSjoerg    else
311*4d6fc14bSjoerg        __throw_system_error(__ec, "thread constructor failed");
312*4d6fc14bSjoerg}
313*4d6fc14bSjoerg
314*4d6fc14bSjoerg#else  // _LIBCPP_CXX03_LANG
315*4d6fc14bSjoerg
316*4d6fc14bSjoergtemplate <class _Fp>
317*4d6fc14bSjoergstruct __thread_invoke_pair {
318*4d6fc14bSjoerg    // This type is used to pass memory for thread local storage and a functor
319*4d6fc14bSjoerg    // to a newly created thread because std::pair doesn't work with
320*4d6fc14bSjoerg    // std::unique_ptr in C++03.
321*4d6fc14bSjoerg    __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
322*4d6fc14bSjoerg    unique_ptr<__thread_struct> __tsp_;
323*4d6fc14bSjoerg    _Fp __fn_;
324*4d6fc14bSjoerg};
325*4d6fc14bSjoerg
326*4d6fc14bSjoergtemplate <class _Fp>
327*4d6fc14bSjoergvoid* __thread_proxy_cxx03(void* __vp)
328*4d6fc14bSjoerg{
329*4d6fc14bSjoerg    unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
330*4d6fc14bSjoerg    __thread_local_data().set_pointer(__p->__tsp_.release());
331*4d6fc14bSjoerg    (__p->__fn_)();
332*4d6fc14bSjoerg    return nullptr;
333*4d6fc14bSjoerg}
334*4d6fc14bSjoerg
335*4d6fc14bSjoergtemplate <class _Fp>
336*4d6fc14bSjoergthread::thread(_Fp __f)
337*4d6fc14bSjoerg{
338*4d6fc14bSjoerg
339*4d6fc14bSjoerg    typedef __thread_invoke_pair<_Fp> _InvokePair;
340*4d6fc14bSjoerg    typedef unique_ptr<_InvokePair> _PairPtr;
341*4d6fc14bSjoerg    _PairPtr __pp(new _InvokePair(__f));
342*4d6fc14bSjoerg    int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
343*4d6fc14bSjoerg    if (__ec == 0)
344*4d6fc14bSjoerg        __pp.release();
345*4d6fc14bSjoerg    else
346*4d6fc14bSjoerg        __throw_system_error(__ec, "thread constructor failed");
347*4d6fc14bSjoerg}
348*4d6fc14bSjoerg
349*4d6fc14bSjoerg#endif // _LIBCPP_CXX03_LANG
350*4d6fc14bSjoerg
351*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
352*4d6fc14bSjoergvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
353*4d6fc14bSjoerg
354*4d6fc14bSjoergnamespace this_thread
355*4d6fc14bSjoerg{
356*4d6fc14bSjoerg
357*4d6fc14bSjoerg_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns);
358*4d6fc14bSjoerg
359*4d6fc14bSjoergtemplate <class _Rep, class _Period>
360*4d6fc14bSjoergvoid
361*4d6fc14bSjoergsleep_for(const chrono::duration<_Rep, _Period>& __d)
362*4d6fc14bSjoerg{
363*4d6fc14bSjoerg    if (__d > chrono::duration<_Rep, _Period>::zero())
364*4d6fc14bSjoerg    {
365*4d6fc14bSjoerg        // The standard guarantees a 64bit signed integer resolution for nanoseconds,
366*4d6fc14bSjoerg        // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits>
367*4d6fc14bSjoerg        // and issues with long double folding on PowerPC with GCC.
368*4d6fc14bSjoerg        _LIBCPP_CONSTEXPR chrono::duration<long double> _Max =
369*4d6fc14bSjoerg            chrono::duration<long double>(9223372036.0L);
370*4d6fc14bSjoerg        chrono::nanoseconds __ns;
371*4d6fc14bSjoerg        if (__d < _Max)
372*4d6fc14bSjoerg        {
373*4d6fc14bSjoerg            __ns = chrono::duration_cast<chrono::nanoseconds>(__d);
374*4d6fc14bSjoerg            if (__ns < __d)
375*4d6fc14bSjoerg                ++__ns;
376*4d6fc14bSjoerg        }
377*4d6fc14bSjoerg        else
378*4d6fc14bSjoerg            __ns = chrono::nanoseconds::max();
379*4d6fc14bSjoerg        this_thread::sleep_for(__ns);
380*4d6fc14bSjoerg    }
381*4d6fc14bSjoerg}
382*4d6fc14bSjoerg
383*4d6fc14bSjoergtemplate <class _Clock, class _Duration>
384*4d6fc14bSjoergvoid
385*4d6fc14bSjoergsleep_until(const chrono::time_point<_Clock, _Duration>& __t)
386*4d6fc14bSjoerg{
387*4d6fc14bSjoerg    mutex __mut;
388*4d6fc14bSjoerg    condition_variable __cv;
389*4d6fc14bSjoerg    unique_lock<mutex> __lk(__mut);
390*4d6fc14bSjoerg    while (_Clock::now() < __t)
391*4d6fc14bSjoerg        __cv.wait_until(__lk, __t);
392*4d6fc14bSjoerg}
393*4d6fc14bSjoerg
394*4d6fc14bSjoergtemplate <class _Duration>
395*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
396*4d6fc14bSjoergvoid
397*4d6fc14bSjoergsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
398*4d6fc14bSjoerg{
399*4d6fc14bSjoerg    this_thread::sleep_for(__t - chrono::steady_clock::now());
400*4d6fc14bSjoerg}
401*4d6fc14bSjoerg
402*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
403*4d6fc14bSjoergvoid yield() _NOEXCEPT {__libcpp_thread_yield();}
404*4d6fc14bSjoerg
405*4d6fc14bSjoerg}  // this_thread
406*4d6fc14bSjoerg
407*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD
408*4d6fc14bSjoerg
409*4d6fc14bSjoerg#endif // !_LIBCPP_HAS_NO_THREADS
410*4d6fc14bSjoerg
411*4d6fc14bSjoerg_LIBCPP_POP_MACROS
412*4d6fc14bSjoerg
413*4d6fc14bSjoerg#endif // _LIBCPP_THREAD
414