xref: /llvm-project-15.0.7/libcxx/include/thread (revision de4a57cb)
13e519524SHoward Hinnant// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
33e519524SHoward Hinnant//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73e519524SHoward Hinnant//
83e519524SHoward Hinnant//===----------------------------------------------------------------------===//
93e519524SHoward Hinnant
103e519524SHoward Hinnant#ifndef _LIBCPP_THREAD
113e519524SHoward Hinnant#define _LIBCPP_THREAD
123e519524SHoward Hinnant
133e519524SHoward Hinnant/*
143e519524SHoward Hinnant
153e519524SHoward Hinnant    thread synopsis
163e519524SHoward Hinnant
173e519524SHoward Hinnantnamespace std
183e519524SHoward Hinnant{
193e519524SHoward Hinnant
203e519524SHoward Hinnantclass thread
213e519524SHoward Hinnant{
223e519524SHoward Hinnantpublic:
233e519524SHoward Hinnant    class id;
243e519524SHoward Hinnant    typedef pthread_t native_handle_type;
253e519524SHoward Hinnant
2636101a5bSHoward Hinnant    thread() noexcept;
273e519524SHoward Hinnant    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
283e519524SHoward Hinnant    ~thread();
293e519524SHoward Hinnant
303e519524SHoward Hinnant    thread(const thread&) = delete;
3136101a5bSHoward Hinnant    thread(thread&& t) noexcept;
323e519524SHoward Hinnant
333e519524SHoward Hinnant    thread& operator=(const thread&) = delete;
3436101a5bSHoward Hinnant    thread& operator=(thread&& t) noexcept;
353e519524SHoward Hinnant
3636101a5bSHoward Hinnant    void swap(thread& t) noexcept;
373e519524SHoward Hinnant
3836101a5bSHoward Hinnant    bool joinable() const noexcept;
393e519524SHoward Hinnant    void join();
403e519524SHoward Hinnant    void detach();
4136101a5bSHoward Hinnant    id get_id() const noexcept;
423e519524SHoward Hinnant    native_handle_type native_handle();
433e519524SHoward Hinnant
4436101a5bSHoward Hinnant    static unsigned hardware_concurrency() noexcept;
453e519524SHoward Hinnant};
463e519524SHoward Hinnant
4736101a5bSHoward Hinnantvoid swap(thread& x, thread& y) noexcept;
483e519524SHoward Hinnant
493e519524SHoward Hinnantclass thread::id
503e519524SHoward Hinnant{
513e519524SHoward Hinnantpublic:
5236101a5bSHoward Hinnant    id() noexcept;
533e519524SHoward Hinnant};
543e519524SHoward Hinnant
5536101a5bSHoward Hinnantbool operator==(thread::id x, thread::id y) noexcept;
5636101a5bSHoward Hinnantbool operator!=(thread::id x, thread::id y) noexcept;
5736101a5bSHoward Hinnantbool operator< (thread::id x, thread::id y) noexcept;
5836101a5bSHoward Hinnantbool operator<=(thread::id x, thread::id y) noexcept;
5936101a5bSHoward Hinnantbool operator> (thread::id x, thread::id y) noexcept;
6036101a5bSHoward Hinnantbool operator>=(thread::id x, thread::id y) noexcept;
613e519524SHoward Hinnant
623e519524SHoward Hinnanttemplate<class charT, class traits>
633e519524SHoward Hinnantbasic_ostream<charT, traits>&
643e519524SHoward Hinnantoperator<<(basic_ostream<charT, traits>& out, thread::id id);
653e519524SHoward Hinnant
663e519524SHoward Hinnantnamespace this_thread
673e519524SHoward Hinnant{
683e519524SHoward Hinnant
6936101a5bSHoward Hinnantthread::id get_id() noexcept;
703e519524SHoward Hinnant
7136101a5bSHoward Hinnantvoid yield() noexcept;
723e519524SHoward Hinnant
733e519524SHoward Hinnanttemplate <class Clock, class Duration>
743e519524SHoward Hinnantvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
753e519524SHoward Hinnant
763e519524SHoward Hinnanttemplate <class Rep, class Period>
773e519524SHoward Hinnantvoid sleep_for(const chrono::duration<Rep, Period>& rel_time);
783e519524SHoward Hinnant
793e519524SHoward Hinnant}  // this_thread
803e519524SHoward Hinnant
813e519524SHoward Hinnant}  // std
823e519524SHoward Hinnant
833e519524SHoward Hinnant*/
843e519524SHoward Hinnant
85385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
863e519524SHoward Hinnant#include <__config>
87976f3705SNikolas Klauser#include <__functional/hash.h>
88bfbd73f8SArthur O'Dwyer#include <__mutex_base>
8992832e48SLouis Dionne#include <__thread/poll_with_backoff.h>
90df51be85SLouis Dionne#include <__thread/timed_backoff_policy.h>
91bfbd73f8SArthur O'Dwyer#include <__threading_support>
926adbc83eSChristopher Di Bella#include <__utility/forward.h>
933e519524SHoward Hinnant#include <cstddef>
94bfbd73f8SArthur O'Dwyer#include <iosfwd>
953e519524SHoward Hinnant#include <memory>
963e519524SHoward Hinnant#include <system_error>
978df61ea8SHoward Hinnant#include <tuple>
98bfbd73f8SArthur O'Dwyer#include <type_traits>
99bd6e6846SMark de Wever#include <version>
1003e519524SHoward Hinnant
101*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
102*de4a57cbSLouis Dionne#  include <chrono>
103*de4a57cbSLouis Dionne#  include <functional>
104*de4a57cbSLouis Dionne#endif
105*de4a57cbSLouis Dionne
106db1978b6SNikolas Klauser// standard-mandated includes
107db1978b6SNikolas Klauser#include <compare>
108db1978b6SNikolas Klauser
109073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1103e519524SHoward Hinnant#  pragma GCC system_header
111073458b1SHoward Hinnant#endif
1123e519524SHoward Hinnant
113a016efb1SEric Fiselier_LIBCPP_PUSH_MACROS
114a016efb1SEric Fiselier#include <__undef_macros>
115a016efb1SEric Fiselier
116b3fcc67fSJonathan Roelofs#ifdef _LIBCPP_HAS_NO_THREADS
1171c4b31c3SLouis Dionne# error "<thread> is not supported since libc++ has been configured without support for threads."
1181c4b31c3SLouis Dionne#endif
119b3fcc67fSJonathan Roelofs
1203e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
1213e519524SHoward Hinnant
1224504cf2cSEric Fiseliertemplate <class _Tp> class __thread_specific_ptr;
1234504cf2cSEric Fiselierclass _LIBCPP_TYPE_VIS __thread_struct;
1244504cf2cSEric Fiselierclass _LIBCPP_HIDDEN __thread_struct_imp;
1254504cf2cSEric Fiselierclass __assoc_sub_state;
1264504cf2cSEric Fiselier
1274504cf2cSEric Fiselier_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1284504cf2cSEric Fiselier
1294504cf2cSEric Fiselierclass _LIBCPP_TYPE_VIS __thread_struct
1304504cf2cSEric Fiselier{
1314504cf2cSEric Fiselier    __thread_struct_imp* __p_;
1324504cf2cSEric Fiselier
1334504cf2cSEric Fiselier    __thread_struct(const __thread_struct&);
1344504cf2cSEric Fiselier    __thread_struct& operator=(const __thread_struct&);
1354504cf2cSEric Fiselierpublic:
1364504cf2cSEric Fiselier    __thread_struct();
1374504cf2cSEric Fiselier    ~__thread_struct();
1384504cf2cSEric Fiselier
1394504cf2cSEric Fiselier    void notify_all_at_thread_exit(condition_variable*, mutex*);
1404504cf2cSEric Fiselier    void __make_ready_at_thread_exit(__assoc_sub_state*);
1414504cf2cSEric Fiselier};
1424504cf2cSEric Fiselier
143167fd108SHoward Hinnanttemplate <class _Tp>
144167fd108SHoward Hinnantclass __thread_specific_ptr
145167fd108SHoward Hinnant{
1468c2bf45dSAsiri Rathnayake    __libcpp_tls_key __key_;
147167fd108SHoward Hinnant
1484504cf2cSEric Fiselier     // Only __thread_local_data() may construct a __thread_specific_ptr
1494504cf2cSEric Fiselier     // and only with _Tp == __thread_struct.
1509a5e62bfSEric Fiselier    static_assert((is_same<_Tp, __thread_struct>::value), "");
1514504cf2cSEric Fiselier    __thread_specific_ptr();
1524504cf2cSEric Fiselier    friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1534504cf2cSEric Fiselier
154167fd108SHoward Hinnant    __thread_specific_ptr(const __thread_specific_ptr&);
155167fd108SHoward Hinnant    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
156167fd108SHoward Hinnant
1579b3222f6SLouis Dionne    _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
1586d7d0becSSaleem Abdulrasool
159167fd108SHoward Hinnantpublic:
160167fd108SHoward Hinnant    typedef _Tp* pointer;
161167fd108SHoward Hinnant
162167fd108SHoward Hinnant    ~__thread_specific_ptr();
163167fd108SHoward Hinnant
164e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
1658c2bf45dSAsiri Rathnayake    pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));}
166e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
167167fd108SHoward Hinnant    pointer operator*() const {return *get();}
168e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
169167fd108SHoward Hinnant    pointer operator->() const {return get();}
170ff94d250SEric Fiselier    void set_pointer(pointer __p);
171167fd108SHoward Hinnant};
172167fd108SHoward Hinnant
173167fd108SHoward Hinnanttemplate <class _Tp>
1746d7d0becSSaleem Abdulrasoolvoid _LIBCPP_TLS_DESTRUCTOR_CC
175167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
176167fd108SHoward Hinnant{
177167fd108SHoward Hinnant    delete static_cast<pointer>(__p);
178167fd108SHoward Hinnant}
179167fd108SHoward Hinnant
180167fd108SHoward Hinnanttemplate <class _Tp>
181167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::__thread_specific_ptr()
182167fd108SHoward Hinnant{
1836d7d0becSSaleem Abdulrasool  int __ec =
1846d7d0becSSaleem Abdulrasool      __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
185167fd108SHoward Hinnant  if (__ec)
1866d7d0becSSaleem Abdulrasool    __throw_system_error(__ec, "__thread_specific_ptr construction failed");
187167fd108SHoward Hinnant}
188167fd108SHoward Hinnant
189167fd108SHoward Hinnanttemplate <class _Tp>
190167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
191167fd108SHoward Hinnant{
1924504cf2cSEric Fiselier    // __thread_specific_ptr is only created with a static storage duration
1934504cf2cSEric Fiselier    // so this destructor is only invoked during program termination. Invoking
1944504cf2cSEric Fiselier    // pthread_key_delete(__key_) may prevent other threads from deleting their
1954504cf2cSEric Fiselier    // thread local data. For this reason we leak the key.
196167fd108SHoward Hinnant}
197167fd108SHoward Hinnant
198167fd108SHoward Hinnanttemplate <class _Tp>
199167fd108SHoward Hinnantvoid
200ff94d250SEric Fiselier__thread_specific_ptr<_Tp>::set_pointer(pointer __p)
201167fd108SHoward Hinnant{
202ff94d250SEric Fiselier    _LIBCPP_ASSERT(get() == nullptr,
203ff94d250SEric Fiselier                   "Attempting to overwrite thread local data");
2048c2bf45dSAsiri Rathnayake    __libcpp_tls_set(__key_, __p);
205167fd108SHoward Hinnant}
206167fd108SHoward Hinnant
2073e519524SHoward Hinnanttemplate<>
208e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
209681cde7dSNikolas Klauser    : public __unary_function<__thread_id, size_t>
2103e519524SHoward Hinnant{
211e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
2127c803385SMarshall Clow    size_t operator()(__thread_id __v) const _NOEXCEPT
2133e519524SHoward Hinnant    {
214c7e4239fSAsiri Rathnayake        return hash<__libcpp_thread_id>()(__v.__id_);
2153e519524SHoward Hinnant    }
2163e519524SHoward Hinnant};
2173e519524SHoward Hinnant
2182b1d4254SMarshall Clowtemplate<class _CharT, class _Traits>
2192b1d4254SMarshall Clow_LIBCPP_INLINE_VISIBILITY
2202b1d4254SMarshall Clowbasic_ostream<_CharT, _Traits>&
2212b1d4254SMarshall Clowoperator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
2222b1d4254SMarshall Clow{return __os << __id.__id_;}
2233e519524SHoward Hinnant
2246e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS thread
2253e519524SHoward Hinnant{
226c7e4239fSAsiri Rathnayake    __libcpp_thread_t __t_;
2273e519524SHoward Hinnant
228eb269257SHoward Hinnant    thread(const thread&);
229eb269257SHoward Hinnant    thread& operator=(const thread&);
2303e519524SHoward Hinnantpublic:
2313e519524SHoward Hinnant    typedef __thread_id id;
232c7e4239fSAsiri Rathnayake    typedef __libcpp_thread_t native_handle_type;
2333e519524SHoward Hinnant
234e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
235af762e91SAsiri Rathnayake    thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
236e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
237c003db1fSHoward Hinnant    template <class _Fp, class ..._Args,
238f7558068SNikolas Klauser              class = __enable_if_t<!is_same<__uncvref_t<_Fp>, thread>::value> >
239bda3c7dfSShoaib Meenai        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
240c003db1fSHoward Hinnant        explicit thread(_Fp&& __f, _Args&&... __args);
241e11fb13bSEric Fiselier#else  // _LIBCPP_CXX03_LANG
242bda3c7dfSShoaib Meenai    template <class _Fp>
243bda3c7dfSShoaib Meenai    _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
244bda3c7dfSShoaib Meenai    explicit thread(_Fp __f);
2453e519524SHoward Hinnant#endif
2463e519524SHoward Hinnant    ~thread();
2473e519524SHoward Hinnant
248e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
24962cfa3a0SLouis Dionne    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {
25062cfa3a0SLouis Dionne        __t.__t_ = _LIBCPP_NULL_THREAD;
25162cfa3a0SLouis Dionne    }
25262cfa3a0SLouis Dionne
253906c872dSEvgeniy Stepanov    _LIBCPP_INLINE_VISIBILITY
25462cfa3a0SLouis Dionne    thread& operator=(thread&& __t) _NOEXCEPT {
25562cfa3a0SLouis Dionne        if (!__libcpp_thread_isnull(&__t_))
25662cfa3a0SLouis Dionne            terminate();
25762cfa3a0SLouis Dionne        __t_ = __t.__t_;
25862cfa3a0SLouis Dionne        __t.__t_ = _LIBCPP_NULL_THREAD;
25962cfa3a0SLouis Dionne        return *this;
26062cfa3a0SLouis Dionne    }
2613e519524SHoward Hinnant
262e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
26336101a5bSHoward Hinnant    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
2643e519524SHoward Hinnant
265e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
266af762e91SAsiri Rathnayake    bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);}
2673e519524SHoward Hinnant    void join();
2683e519524SHoward Hinnant    void detach();
269e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
270c7e4239fSAsiri Rathnayake    id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);}
271e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
27236101a5bSHoward Hinnant    native_handle_type native_handle() _NOEXCEPT {return __t_;}
2733e519524SHoward Hinnant
27436101a5bSHoward Hinnant    static unsigned hardware_concurrency() _NOEXCEPT;
2753e519524SHoward Hinnant};
2763e519524SHoward Hinnant
277e11fb13bSEric Fiselier#ifndef _LIBCPP_CXX03_LANG
2788df61ea8SHoward Hinnant
279e08afaf8SEric Fiseliertemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices>
2808df61ea8SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
2818df61ea8SHoward Hinnantvoid
282e08afaf8SEric Fiselier__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>)
2838df61ea8SHoward Hinnant{
28440950a44SArthur O'Dwyer    _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
2858df61ea8SHoward Hinnant}
2868df61ea8SHoward Hinnant
287c003db1fSHoward Hinnanttemplate <class _Fp>
288dd37e24aSLouis Dionne_LIBCPP_INLINE_VISIBILITY
289e08afaf8SEric Fiseliervoid* __thread_proxy(void* __vp)
2908df61ea8SHoward Hinnant{
29140950a44SArthur O'Dwyer    // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...>
29240950a44SArthur O'Dwyer    unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
29340950a44SArthur O'Dwyer    __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release());
294e08afaf8SEric Fiselier    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
29540950a44SArthur O'Dwyer    _VSTD::__thread_execute(*__p.get(), _Index());
2968df61ea8SHoward Hinnant    return nullptr;
2978df61ea8SHoward Hinnant}
2988df61ea8SHoward Hinnant
299c003db1fSHoward Hinnanttemplate <class _Fp, class ..._Args,
3008df61ea8SHoward Hinnant          class
3018df61ea8SHoward Hinnant         >
302c003db1fSHoward Hinnantthread::thread(_Fp&& __f, _Args&&... __args)
3038df61ea8SHoward Hinnant{
304e08afaf8SEric Fiselier    typedef unique_ptr<__thread_struct> _TSPtr;
305e08afaf8SEric Fiselier    _TSPtr __tsp(new __thread_struct);
306e08afaf8SEric Fiselier    typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
30740950a44SArthur O'Dwyer    unique_ptr<_Gp> __p(
30840950a44SArthur O'Dwyer            new _Gp(_VSTD::move(__tsp),
309cb8a0b07SArthur O'Dwyer                    _VSTD::forward<_Fp>(__f),
310cb8a0b07SArthur O'Dwyer                    _VSTD::forward<_Args>(__args)...));
31140950a44SArthur O'Dwyer    int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
3128df61ea8SHoward Hinnant    if (__ec == 0)
3138df61ea8SHoward Hinnant        __p.release();
3148df61ea8SHoward Hinnant    else
3158df61ea8SHoward Hinnant        __throw_system_error(__ec, "thread constructor failed");
3168df61ea8SHoward Hinnant}
3178df61ea8SHoward Hinnant
318e11fb13bSEric Fiselier#else  // _LIBCPP_CXX03_LANG
3198df61ea8SHoward Hinnant
320c003db1fSHoward Hinnanttemplate <class _Fp>
321e08afaf8SEric Fiselierstruct __thread_invoke_pair {
322e08afaf8SEric Fiselier    // This type is used to pass memory for thread local storage and a functor
323e08afaf8SEric Fiselier    // to a newly created thread because std::pair doesn't work with
324e08afaf8SEric Fiselier    // std::unique_ptr in C++03.
325e08afaf8SEric Fiselier    __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
326e08afaf8SEric Fiselier    unique_ptr<__thread_struct> __tsp_;
327e08afaf8SEric Fiselier    _Fp __fn_;
328e08afaf8SEric Fiselier};
329e08afaf8SEric Fiselier
330e08afaf8SEric Fiseliertemplate <class _Fp>
331e08afaf8SEric Fiseliervoid* __thread_proxy_cxx03(void* __vp)
3323e519524SHoward Hinnant{
33340950a44SArthur O'Dwyer    unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
334ff94d250SEric Fiselier    __thread_local_data().set_pointer(__p->__tsp_.release());
335e08afaf8SEric Fiselier    (__p->__fn_)();
3363e519524SHoward Hinnant    return nullptr;
3373e519524SHoward Hinnant}
3383e519524SHoward Hinnant
339c003db1fSHoward Hinnanttemplate <class _Fp>
340c003db1fSHoward Hinnantthread::thread(_Fp __f)
3413e519524SHoward Hinnant{
342e08afaf8SEric Fiselier
343e08afaf8SEric Fiselier    typedef __thread_invoke_pair<_Fp> _InvokePair;
34440950a44SArthur O'Dwyer    typedef unique_ptr<_InvokePair> _PairPtr;
345e08afaf8SEric Fiselier    _PairPtr __pp(new _InvokePair(__f));
34640950a44SArthur O'Dwyer    int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
3473e519524SHoward Hinnant    if (__ec == 0)
348e08afaf8SEric Fiselier        __pp.release();
3493e519524SHoward Hinnant    else
3503e519524SHoward Hinnant        __throw_system_error(__ec, "thread constructor failed");
3513e519524SHoward Hinnant}
3523e519524SHoward Hinnant
353e11fb13bSEric Fiselier#endif // _LIBCPP_CXX03_LANG
3543e519524SHoward Hinnant
355e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
35636101a5bSHoward Hinnantvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
3573e519524SHoward Hinnant
3583e519524SHoward Hinnantnamespace this_thread
3593e519524SHoward Hinnant{
3603e519524SHoward Hinnant
3619e8a082dSJoerg Sonnenberger_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns);
3623e519524SHoward Hinnant
3633e519524SHoward Hinnanttemplate <class _Rep, class _Period>
3643e519524SHoward Hinnantvoid
3653e519524SHoward Hinnantsleep_for(const chrono::duration<_Rep, _Period>& __d)
3663e519524SHoward Hinnant{
36740950a44SArthur O'Dwyer    if (__d > chrono::duration<_Rep, _Period>::zero())
368aad745a0SHoward Hinnant    {
3699f4022ffSJoerg Sonnenberger        // The standard guarantees a 64bit signed integer resolution for nanoseconds,
3709f4022ffSJoerg Sonnenberger        // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits>
3719f4022ffSJoerg Sonnenberger        // and issues with long double folding on PowerPC with GCC.
3729f4022ffSJoerg Sonnenberger        _LIBCPP_CONSTEXPR chrono::duration<long double> _Max =
3739f4022ffSJoerg Sonnenberger            chrono::duration<long double>(9223372036.0L);
37440950a44SArthur O'Dwyer        chrono::nanoseconds __ns;
375aad745a0SHoward Hinnant        if (__d < _Max)
376aad745a0SHoward Hinnant        {
37740950a44SArthur O'Dwyer            __ns = chrono::duration_cast<chrono::nanoseconds>(__d);
3783e519524SHoward Hinnant            if (__ns < __d)
3793e519524SHoward Hinnant                ++__ns;
380aad745a0SHoward Hinnant        }
381aad745a0SHoward Hinnant        else
38240950a44SArthur O'Dwyer            __ns = chrono::nanoseconds::max();
38340950a44SArthur O'Dwyer        this_thread::sleep_for(__ns);
3843e519524SHoward Hinnant    }
385aad745a0SHoward Hinnant}
3863e519524SHoward Hinnant
3873e519524SHoward Hinnanttemplate <class _Clock, class _Duration>
3883e519524SHoward Hinnantvoid
3893e519524SHoward Hinnantsleep_until(const chrono::time_point<_Clock, _Duration>& __t)
3903e519524SHoward Hinnant{
3913e519524SHoward Hinnant    mutex __mut;
3923e519524SHoward Hinnant    condition_variable __cv;
3933e519524SHoward Hinnant    unique_lock<mutex> __lk(__mut);
3943e519524SHoward Hinnant    while (_Clock::now() < __t)
3953e519524SHoward Hinnant        __cv.wait_until(__lk, __t);
3963e519524SHoward Hinnant}
3973e519524SHoward Hinnant
3983e519524SHoward Hinnanttemplate <class _Duration>
399e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
4003e519524SHoward Hinnantvoid
4013dc6455fSHoward Hinnantsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
4023e519524SHoward Hinnant{
40340950a44SArthur O'Dwyer    this_thread::sleep_for(__t - chrono::steady_clock::now());
4043e519524SHoward Hinnant}
4053e519524SHoward Hinnant
406e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
407c7e4239fSAsiri Rathnayakevoid yield() _NOEXCEPT {__libcpp_thread_yield();}
4083e519524SHoward Hinnant
409d2b0df35SNikolas Klauser} // namespace this_thread
4103e519524SHoward Hinnant
4113e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
4123e519524SHoward Hinnant
413a016efb1SEric Fiselier_LIBCPP_POP_MACROS
414a016efb1SEric Fiselier
4153e519524SHoward Hinnant#endif // _LIBCPP_THREAD
416