xref: /freebsd-12.1/contrib/libc++/include/thread (revision 4173b67f)
17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===--------------------------- thread -----------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP_THREAD
127a984708SDavid Chisnall#define _LIBCPP_THREAD
137a984708SDavid Chisnall
147a984708SDavid Chisnall/*
157a984708SDavid Chisnall
167a984708SDavid Chisnall    thread synopsis
177a984708SDavid Chisnall
187a984708SDavid Chisnall#define __STDCPP_THREADS__ __cplusplus
197a984708SDavid Chisnall
207a984708SDavid Chisnallnamespace std
217a984708SDavid Chisnall{
227a984708SDavid Chisnall
237a984708SDavid Chisnallclass thread
247a984708SDavid Chisnall{
257a984708SDavid Chisnallpublic:
267a984708SDavid Chisnall    class id;
277a984708SDavid Chisnall    typedef pthread_t native_handle_type;
287a984708SDavid Chisnall
29936e9439SDimitry Andric    thread() noexcept;
307a984708SDavid Chisnall    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
317a984708SDavid Chisnall    ~thread();
327a984708SDavid Chisnall
337a984708SDavid Chisnall    thread(const thread&) = delete;
34936e9439SDimitry Andric    thread(thread&& t) noexcept;
357a984708SDavid Chisnall
367a984708SDavid Chisnall    thread& operator=(const thread&) = delete;
37936e9439SDimitry Andric    thread& operator=(thread&& t) noexcept;
387a984708SDavid Chisnall
39936e9439SDimitry Andric    void swap(thread& t) noexcept;
407a984708SDavid Chisnall
41936e9439SDimitry Andric    bool joinable() const noexcept;
427a984708SDavid Chisnall    void join();
437a984708SDavid Chisnall    void detach();
44936e9439SDimitry Andric    id get_id() const noexcept;
457a984708SDavid Chisnall    native_handle_type native_handle();
467a984708SDavid Chisnall
47936e9439SDimitry Andric    static unsigned hardware_concurrency() noexcept;
487a984708SDavid Chisnall};
497a984708SDavid Chisnall
50936e9439SDimitry Andricvoid swap(thread& x, thread& y) noexcept;
517a984708SDavid Chisnall
527a984708SDavid Chisnallclass thread::id
537a984708SDavid Chisnall{
547a984708SDavid Chisnallpublic:
55936e9439SDimitry Andric    id() noexcept;
567a984708SDavid Chisnall};
577a984708SDavid Chisnall
58936e9439SDimitry Andricbool operator==(thread::id x, thread::id y) noexcept;
59936e9439SDimitry Andricbool operator!=(thread::id x, thread::id y) noexcept;
60936e9439SDimitry Andricbool operator< (thread::id x, thread::id y) noexcept;
61936e9439SDimitry Andricbool operator<=(thread::id x, thread::id y) noexcept;
62936e9439SDimitry Andricbool operator> (thread::id x, thread::id y) noexcept;
63936e9439SDimitry Andricbool operator>=(thread::id x, thread::id y) noexcept;
647a984708SDavid Chisnall
657a984708SDavid Chisnalltemplate<class charT, class traits>
667a984708SDavid Chisnallbasic_ostream<charT, traits>&
677a984708SDavid Chisnalloperator<<(basic_ostream<charT, traits>& out, thread::id id);
687a984708SDavid Chisnall
697a984708SDavid Chisnallnamespace this_thread
707a984708SDavid Chisnall{
717a984708SDavid Chisnall
72936e9439SDimitry Andricthread::id get_id() noexcept;
737a984708SDavid Chisnall
74936e9439SDimitry Andricvoid yield() noexcept;
757a984708SDavid Chisnall
767a984708SDavid Chisnalltemplate <class Clock, class Duration>
777a984708SDavid Chisnallvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
787a984708SDavid Chisnall
797a984708SDavid Chisnalltemplate <class Rep, class Period>
807a984708SDavid Chisnallvoid sleep_for(const chrono::duration<Rep, Period>& rel_time);
817a984708SDavid Chisnall
827a984708SDavid Chisnall}  // this_thread
837a984708SDavid Chisnall
847a984708SDavid Chisnall}  // std
857a984708SDavid Chisnall
867a984708SDavid Chisnall*/
877a984708SDavid Chisnall
887a984708SDavid Chisnall#include <__config>
897a984708SDavid Chisnall#include <iosfwd>
907a984708SDavid Chisnall#include <__functional_base>
917a984708SDavid Chisnall#include <type_traits>
927a984708SDavid Chisnall#include <cstddef>
937a984708SDavid Chisnall#include <functional>
947a984708SDavid Chisnall#include <memory>
957a984708SDavid Chisnall#include <system_error>
967a984708SDavid Chisnall#include <chrono>
977a984708SDavid Chisnall#include <__mutex_base>
98540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
997a984708SDavid Chisnall#include <tuple>
1007a984708SDavid Chisnall#endif
1017c82a1ecSDimitry Andric#include <__threading_support>
102aed8d94eSDimitry Andric#include <__debug>
1037a984708SDavid Chisnall
1047a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1057a984708SDavid Chisnall#pragma GCC system_header
1067a984708SDavid Chisnall#endif
1077a984708SDavid Chisnall
108f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
109f9448bf3SDimitry Andric#include <__undef_macros>
110f9448bf3SDimitry Andric
1117a984708SDavid Chisnall#define __STDCPP_THREADS__ __cplusplus
1127a984708SDavid Chisnall
113d72607e9SDimitry Andric#ifdef _LIBCPP_HAS_NO_THREADS
114d72607e9SDimitry Andric#error <thread> is not supported on this single threaded system
115d72607e9SDimitry Andric#else // !_LIBCPP_HAS_NO_THREADS
116d72607e9SDimitry Andric
1177a984708SDavid Chisnall_LIBCPP_BEGIN_NAMESPACE_STD
1187a984708SDavid Chisnall
1199729cf09SDimitry Andrictemplate <class _Tp> class __thread_specific_ptr;
1209729cf09SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct;
1219729cf09SDimitry Andricclass _LIBCPP_HIDDEN __thread_struct_imp;
1229729cf09SDimitry Andricclass __assoc_sub_state;
1239729cf09SDimitry Andric
1249729cf09SDimitry Andric_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1259729cf09SDimitry Andric
1269729cf09SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct
1279729cf09SDimitry Andric{
1289729cf09SDimitry Andric    __thread_struct_imp* __p_;
1299729cf09SDimitry Andric
1309729cf09SDimitry Andric    __thread_struct(const __thread_struct&);
1319729cf09SDimitry Andric    __thread_struct& operator=(const __thread_struct&);
1329729cf09SDimitry Andricpublic:
1339729cf09SDimitry Andric    __thread_struct();
1349729cf09SDimitry Andric    ~__thread_struct();
1359729cf09SDimitry Andric
1369729cf09SDimitry Andric    void notify_all_at_thread_exit(condition_variable*, mutex*);
1379729cf09SDimitry Andric    void __make_ready_at_thread_exit(__assoc_sub_state*);
1389729cf09SDimitry Andric};
1399729cf09SDimitry Andric
1407a984708SDavid Chisnalltemplate <class _Tp>
1417a984708SDavid Chisnallclass __thread_specific_ptr
1427a984708SDavid Chisnall{
143aed8d94eSDimitry Andric    __libcpp_tls_key __key_;
1447a984708SDavid Chisnall
1459729cf09SDimitry Andric     // Only __thread_local_data() may construct a __thread_specific_ptr
1469729cf09SDimitry Andric     // and only with _Tp == __thread_struct.
1479729cf09SDimitry Andric    static_assert((is_same<_Tp, __thread_struct>::value), "");
1489729cf09SDimitry Andric    __thread_specific_ptr();
1499729cf09SDimitry Andric    friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1509729cf09SDimitry Andric
1517a984708SDavid Chisnall    __thread_specific_ptr(const __thread_specific_ptr&);
1527a984708SDavid Chisnall    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
1537a984708SDavid Chisnall
154b5893f02SDimitry Andric    _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
15580779b37SDimitry Andric
1567a984708SDavid Chisnallpublic:
1577a984708SDavid Chisnall    typedef _Tp* pointer;
1587a984708SDavid Chisnall
1597a984708SDavid Chisnall    ~__thread_specific_ptr();
1607a984708SDavid Chisnall
1617a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
162aed8d94eSDimitry Andric    pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));}
1637a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1647a984708SDavid Chisnall    pointer operator*() const {return *get();}
1657a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
1667a984708SDavid Chisnall    pointer operator->() const {return get();}
167aed8d94eSDimitry Andric    void set_pointer(pointer __p);
1687a984708SDavid Chisnall};
1697a984708SDavid Chisnall
1707a984708SDavid Chisnalltemplate <class _Tp>
17180779b37SDimitry Andricvoid _LIBCPP_TLS_DESTRUCTOR_CC
1727a984708SDavid Chisnall__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
1737a984708SDavid Chisnall{
1747a984708SDavid Chisnall    delete static_cast<pointer>(__p);
1757a984708SDavid Chisnall}
1767a984708SDavid Chisnall
1777a984708SDavid Chisnalltemplate <class _Tp>
1787a984708SDavid Chisnall__thread_specific_ptr<_Tp>::__thread_specific_ptr()
1797a984708SDavid Chisnall{
18080779b37SDimitry Andric  int __ec =
18180779b37SDimitry Andric      __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
1827a984708SDavid Chisnall  if (__ec)
18380779b37SDimitry Andric    __throw_system_error(__ec, "__thread_specific_ptr construction failed");
1847a984708SDavid Chisnall}
1857a984708SDavid Chisnall
1867a984708SDavid Chisnalltemplate <class _Tp>
1877a984708SDavid Chisnall__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
1887a984708SDavid Chisnall{
1899729cf09SDimitry Andric    // __thread_specific_ptr is only created with a static storage duration
1909729cf09SDimitry Andric    // so this destructor is only invoked during program termination. Invoking
1919729cf09SDimitry Andric    // pthread_key_delete(__key_) may prevent other threads from deleting their
1929729cf09SDimitry Andric    // thread local data. For this reason we leak the key.
1937a984708SDavid Chisnall}
1947a984708SDavid Chisnall
1957a984708SDavid Chisnalltemplate <class _Tp>
1967a984708SDavid Chisnallvoid
197aed8d94eSDimitry Andric__thread_specific_ptr<_Tp>::set_pointer(pointer __p)
1987a984708SDavid Chisnall{
199aed8d94eSDimitry Andric    _LIBCPP_ASSERT(get() == nullptr,
200aed8d94eSDimitry Andric                   "Attempting to overwrite thread local data");
201aed8d94eSDimitry Andric    __libcpp_tls_set(__key_, __p);
2027a984708SDavid Chisnall}
2037a984708SDavid Chisnall
2047a984708SDavid Chisnalltemplate<>
205aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
2067a984708SDavid Chisnall    : public unary_function<__thread_id, size_t>
2077a984708SDavid Chisnall{
2087a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
209540d2a8bSDimitry Andric    size_t operator()(__thread_id __v) const _NOEXCEPT
2107a984708SDavid Chisnall    {
2117c82a1ecSDimitry Andric        return hash<__libcpp_thread_id>()(__v.__id_);
2127a984708SDavid Chisnall    }
2137a984708SDavid Chisnall};
2147a984708SDavid Chisnall
215*4173b67fSDimitry Andrictemplate<class _CharT, class _Traits>
216*4173b67fSDimitry Andric_LIBCPP_INLINE_VISIBILITY
217*4173b67fSDimitry Andricbasic_ostream<_CharT, _Traits>&
218*4173b67fSDimitry Andricoperator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
219*4173b67fSDimitry Andric{return __os << __id.__id_;}
2207a984708SDavid Chisnall
2211bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS thread
2227a984708SDavid Chisnall{
2237c82a1ecSDimitry Andric    __libcpp_thread_t __t_;
2247a984708SDavid Chisnall
2257a984708SDavid Chisnall    thread(const thread&);
2267a984708SDavid Chisnall    thread& operator=(const thread&);
2277a984708SDavid Chisnallpublic:
2287a984708SDavid Chisnall    typedef __thread_id id;
2297c82a1ecSDimitry Andric    typedef __libcpp_thread_t native_handle_type;
2307a984708SDavid Chisnall
2317a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
232540d2a8bSDimitry Andric    thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
233540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
23494e3ee44SDavid Chisnall    template <class _Fp, class ..._Args,
2357a984708SDavid Chisnall              class = typename enable_if
2367a984708SDavid Chisnall              <
2374ba319b5SDimitry Andric                   !is_same<typename __uncvref<_Fp>::type, thread>::value
2387a984708SDavid Chisnall              >::type
2397a984708SDavid Chisnall             >
240540d2a8bSDimitry Andric        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
24194e3ee44SDavid Chisnall        explicit thread(_Fp&& __f, _Args&&... __args);
242540d2a8bSDimitry Andric#else  // _LIBCPP_CXX03_LANG
243540d2a8bSDimitry Andric    template <class _Fp>
244540d2a8bSDimitry Andric    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
245540d2a8bSDimitry Andric    explicit thread(_Fp __f);
2467a984708SDavid Chisnall#endif
2477a984708SDavid Chisnall    ~thread();
2487a984708SDavid Chisnall
249540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
2507a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
251540d2a8bSDimitry Andric    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;}
2529729cf09SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
253936e9439SDimitry Andric    thread& operator=(thread&& __t) _NOEXCEPT;
254540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
2557a984708SDavid Chisnall
2567a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
257936e9439SDimitry Andric    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
2587a984708SDavid Chisnall
2597a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
260540d2a8bSDimitry Andric    bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);}
2617a984708SDavid Chisnall    void join();
2627a984708SDavid Chisnall    void detach();
2637a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
2647c82a1ecSDimitry Andric    id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);}
2657a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY
266936e9439SDimitry Andric    native_handle_type native_handle() _NOEXCEPT {return __t_;}
2677a984708SDavid Chisnall
268936e9439SDimitry Andric    static unsigned hardware_concurrency() _NOEXCEPT;
2697a984708SDavid Chisnall};
2707a984708SDavid Chisnall
271540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
2727a984708SDavid Chisnall
2737c82a1ecSDimitry Andrictemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices>
2747a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
2757a984708SDavid Chisnallvoid
2767c82a1ecSDimitry Andric__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>)
2777a984708SDavid Chisnall{
2787c82a1ecSDimitry Andric    __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
2797a984708SDavid Chisnall}
2807a984708SDavid Chisnall
28194e3ee44SDavid Chisnalltemplate <class _Fp>
2827c82a1ecSDimitry Andricvoid* __thread_proxy(void* __vp)
2837a984708SDavid Chisnall{
2847c82a1ecSDimitry Andric    // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...>
28594e3ee44SDavid Chisnall    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
286aed8d94eSDimitry Andric    __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release());
2877c82a1ecSDimitry Andric    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
2881bf9f7c1SDimitry Andric    __thread_execute(*__p, _Index());
2897a984708SDavid Chisnall    return nullptr;
2907a984708SDavid Chisnall}
2917a984708SDavid Chisnall
29294e3ee44SDavid Chisnalltemplate <class _Fp, class ..._Args,
2937a984708SDavid Chisnall          class
2947a984708SDavid Chisnall         >
29594e3ee44SDavid Chisnallthread::thread(_Fp&& __f, _Args&&... __args)
2967a984708SDavid Chisnall{
2977c82a1ecSDimitry Andric    typedef unique_ptr<__thread_struct> _TSPtr;
2987c82a1ecSDimitry Andric    _TSPtr __tsp(new __thread_struct);
2997c82a1ecSDimitry Andric    typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
3007c82a1ecSDimitry Andric    _VSTD::unique_ptr<_Gp> __p(
3017c82a1ecSDimitry Andric            new _Gp(std::move(__tsp),
3027c82a1ecSDimitry Andric                    __decay_copy(_VSTD::forward<_Fp>(__f)),
3037a984708SDavid Chisnall                    __decay_copy(_VSTD::forward<_Args>(__args))...));
3047c82a1ecSDimitry Andric    int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
3057a984708SDavid Chisnall    if (__ec == 0)
3067a984708SDavid Chisnall        __p.release();
3077a984708SDavid Chisnall    else
3087a984708SDavid Chisnall        __throw_system_error(__ec, "thread constructor failed");
3097a984708SDavid Chisnall}
3107a984708SDavid Chisnall
311540d2a8bSDimitry Andricinline
312540d2a8bSDimitry Andricthread&
313540d2a8bSDimitry Andricthread::operator=(thread&& __t) _NOEXCEPT
314540d2a8bSDimitry Andric{
315540d2a8bSDimitry Andric    if (!__libcpp_thread_isnull(&__t_))
316540d2a8bSDimitry Andric        terminate();
317540d2a8bSDimitry Andric    __t_ = __t.__t_;
318540d2a8bSDimitry Andric    __t.__t_ = _LIBCPP_NULL_THREAD;
319540d2a8bSDimitry Andric    return *this;
320540d2a8bSDimitry Andric}
321540d2a8bSDimitry Andric
322540d2a8bSDimitry Andric#else  // _LIBCPP_CXX03_LANG
3237a984708SDavid Chisnall
32494e3ee44SDavid Chisnalltemplate <class _Fp>
3257c82a1ecSDimitry Andricstruct __thread_invoke_pair {
3267c82a1ecSDimitry Andric    // This type is used to pass memory for thread local storage and a functor
3277c82a1ecSDimitry Andric    // to a newly created thread because std::pair doesn't work with
3287c82a1ecSDimitry Andric    // std::unique_ptr in C++03.
3297c82a1ecSDimitry Andric    __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
3307c82a1ecSDimitry Andric    unique_ptr<__thread_struct> __tsp_;
3317c82a1ecSDimitry Andric    _Fp __fn_;
3327c82a1ecSDimitry Andric};
3337c82a1ecSDimitry Andric
3347c82a1ecSDimitry Andrictemplate <class _Fp>
3357c82a1ecSDimitry Andricvoid* __thread_proxy_cxx03(void* __vp)
3367a984708SDavid Chisnall{
33794e3ee44SDavid Chisnall    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
338aed8d94eSDimitry Andric    __thread_local_data().set_pointer(__p->__tsp_.release());
3397c82a1ecSDimitry Andric    (__p->__fn_)();
3407a984708SDavid Chisnall    return nullptr;
3417a984708SDavid Chisnall}
3427a984708SDavid Chisnall
34394e3ee44SDavid Chisnalltemplate <class _Fp>
34494e3ee44SDavid Chisnallthread::thread(_Fp __f)
3457a984708SDavid Chisnall{
3467c82a1ecSDimitry Andric
3477c82a1ecSDimitry Andric    typedef __thread_invoke_pair<_Fp> _InvokePair;
3487c82a1ecSDimitry Andric    typedef std::unique_ptr<_InvokePair> _PairPtr;
3497c82a1ecSDimitry Andric    _PairPtr __pp(new _InvokePair(__f));
3507c82a1ecSDimitry Andric    int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
3517a984708SDavid Chisnall    if (__ec == 0)
3527c82a1ecSDimitry Andric        __pp.release();
3537a984708SDavid Chisnall    else
3547a984708SDavid Chisnall        __throw_system_error(__ec, "thread constructor failed");
3557a984708SDavid Chisnall}
3567a984708SDavid Chisnall
357540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
3587a984708SDavid Chisnall
3597a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
360936e9439SDimitry Andricvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
3617a984708SDavid Chisnall
3627a984708SDavid Chisnallnamespace this_thread
3637a984708SDavid Chisnall{
3647a984708SDavid Chisnall
365540d2a8bSDimitry Andric_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns);
3667a984708SDavid Chisnall
3677a984708SDavid Chisnalltemplate <class _Rep, class _Period>
3687a984708SDavid Chisnallvoid
3697a984708SDavid Chisnallsleep_for(const chrono::duration<_Rep, _Period>& __d)
3707a984708SDavid Chisnall{
3717a984708SDavid Chisnall    using namespace chrono;
372936e9439SDimitry Andric    if (__d > duration<_Rep, _Period>::zero())
373936e9439SDimitry Andric    {
374936e9439SDimitry Andric        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
375936e9439SDimitry Andric        nanoseconds __ns;
376936e9439SDimitry Andric        if (__d < _Max)
377936e9439SDimitry Andric        {
378936e9439SDimitry Andric            __ns = duration_cast<nanoseconds>(__d);
3797a984708SDavid Chisnall            if (__ns < __d)
3807a984708SDavid Chisnall                ++__ns;
381936e9439SDimitry Andric        }
382936e9439SDimitry Andric        else
383936e9439SDimitry Andric            __ns = nanoseconds::max();
3847a984708SDavid Chisnall        sleep_for(__ns);
3857a984708SDavid Chisnall    }
386936e9439SDimitry Andric}
3877a984708SDavid Chisnall
3887a984708SDavid Chisnalltemplate <class _Clock, class _Duration>
3897a984708SDavid Chisnallvoid
3907a984708SDavid Chisnallsleep_until(const chrono::time_point<_Clock, _Duration>& __t)
3917a984708SDavid Chisnall{
3927a984708SDavid Chisnall    using namespace chrono;
3937a984708SDavid Chisnall    mutex __mut;
3947a984708SDavid Chisnall    condition_variable __cv;
3957a984708SDavid Chisnall    unique_lock<mutex> __lk(__mut);
3967a984708SDavid Chisnall    while (_Clock::now() < __t)
3977a984708SDavid Chisnall        __cv.wait_until(__lk, __t);
3987a984708SDavid Chisnall}
3997a984708SDavid Chisnall
4007a984708SDavid Chisnalltemplate <class _Duration>
4017a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
4027a984708SDavid Chisnallvoid
4037a984708SDavid Chisnallsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
4047a984708SDavid Chisnall{
4057a984708SDavid Chisnall    using namespace chrono;
4067a984708SDavid Chisnall    sleep_for(__t - steady_clock::now());
4077a984708SDavid Chisnall}
4087a984708SDavid Chisnall
4097a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
4107c82a1ecSDimitry Andricvoid yield() _NOEXCEPT {__libcpp_thread_yield();}
4117a984708SDavid Chisnall
4127a984708SDavid Chisnall}  // this_thread
4137a984708SDavid Chisnall
4147a984708SDavid Chisnall_LIBCPP_END_NAMESPACE_STD
4157a984708SDavid Chisnall
416d72607e9SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS
417d72607e9SDimitry Andric
418f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
419f9448bf3SDimitry Andric
4207a984708SDavid Chisnall#endif  // _LIBCPP_THREAD
421