xref: /llvm-project-15.0.7/libcxx/include/thread (revision 9e8a082d)
13e519524SHoward Hinnant// -*- C++ -*-
23e519524SHoward Hinnant//===--------------------------- thread -----------------------------------===//
33e519524SHoward Hinnant//
45b08a8a4SHoward Hinnant//                     The LLVM Compiler Infrastructure
53e519524SHoward Hinnant//
6412dbebeSHoward Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
7412dbebeSHoward Hinnant// Source Licenses. See LICENSE.TXT for details.
83e519524SHoward Hinnant//
93e519524SHoward Hinnant//===----------------------------------------------------------------------===//
103e519524SHoward Hinnant
113e519524SHoward Hinnant#ifndef _LIBCPP_THREAD
123e519524SHoward Hinnant#define _LIBCPP_THREAD
133e519524SHoward Hinnant
143e519524SHoward Hinnant/*
153e519524SHoward Hinnant
163e519524SHoward Hinnant    thread synopsis
173e519524SHoward Hinnant
18e8e7af24SHoward Hinnant#define __STDCPP_THREADS__ __cplusplus
193e519524SHoward Hinnant
203e519524SHoward Hinnantnamespace std
213e519524SHoward Hinnant{
223e519524SHoward Hinnant
233e519524SHoward Hinnantclass thread
243e519524SHoward Hinnant{
253e519524SHoward Hinnantpublic:
263e519524SHoward Hinnant    class id;
273e519524SHoward Hinnant    typedef pthread_t native_handle_type;
283e519524SHoward Hinnant
2936101a5bSHoward Hinnant    thread() noexcept;
303e519524SHoward Hinnant    template <class F, class ...Args> explicit thread(F&& f, Args&&... args);
313e519524SHoward Hinnant    ~thread();
323e519524SHoward Hinnant
333e519524SHoward Hinnant    thread(const thread&) = delete;
3436101a5bSHoward Hinnant    thread(thread&& t) noexcept;
353e519524SHoward Hinnant
363e519524SHoward Hinnant    thread& operator=(const thread&) = delete;
3736101a5bSHoward Hinnant    thread& operator=(thread&& t) noexcept;
383e519524SHoward Hinnant
3936101a5bSHoward Hinnant    void swap(thread& t) noexcept;
403e519524SHoward Hinnant
4136101a5bSHoward Hinnant    bool joinable() const noexcept;
423e519524SHoward Hinnant    void join();
433e519524SHoward Hinnant    void detach();
4436101a5bSHoward Hinnant    id get_id() const noexcept;
453e519524SHoward Hinnant    native_handle_type native_handle();
463e519524SHoward Hinnant
4736101a5bSHoward Hinnant    static unsigned hardware_concurrency() noexcept;
483e519524SHoward Hinnant};
493e519524SHoward Hinnant
5036101a5bSHoward Hinnantvoid swap(thread& x, thread& y) noexcept;
513e519524SHoward Hinnant
523e519524SHoward Hinnantclass thread::id
533e519524SHoward Hinnant{
543e519524SHoward Hinnantpublic:
5536101a5bSHoward Hinnant    id() noexcept;
563e519524SHoward Hinnant};
573e519524SHoward Hinnant
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;
6136101a5bSHoward Hinnantbool operator<=(thread::id x, thread::id y) noexcept;
6236101a5bSHoward Hinnantbool operator> (thread::id x, thread::id y) noexcept;
6336101a5bSHoward Hinnantbool operator>=(thread::id x, thread::id y) noexcept;
643e519524SHoward Hinnant
653e519524SHoward Hinnanttemplate<class charT, class traits>
663e519524SHoward Hinnantbasic_ostream<charT, traits>&
673e519524SHoward Hinnantoperator<<(basic_ostream<charT, traits>& out, thread::id id);
683e519524SHoward Hinnant
693e519524SHoward Hinnantnamespace this_thread
703e519524SHoward Hinnant{
713e519524SHoward Hinnant
7236101a5bSHoward Hinnantthread::id get_id() noexcept;
733e519524SHoward Hinnant
7436101a5bSHoward Hinnantvoid yield() noexcept;
753e519524SHoward Hinnant
763e519524SHoward Hinnanttemplate <class Clock, class Duration>
773e519524SHoward Hinnantvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
783e519524SHoward Hinnant
793e519524SHoward Hinnanttemplate <class Rep, class Period>
803e519524SHoward Hinnantvoid sleep_for(const chrono::duration<Rep, Period>& rel_time);
813e519524SHoward Hinnant
823e519524SHoward Hinnant}  // this_thread
833e519524SHoward Hinnant
843e519524SHoward Hinnant}  // std
853e519524SHoward Hinnant
863e519524SHoward Hinnant*/
873e519524SHoward Hinnant
883e519524SHoward Hinnant#include <__config>
893e519524SHoward Hinnant#include <iosfwd>
903e519524SHoward Hinnant#include <__functional_base>
913e519524SHoward Hinnant#include <type_traits>
923e519524SHoward Hinnant#include <cstddef>
933e519524SHoward Hinnant#include <functional>
943e519524SHoward Hinnant#include <memory>
953e519524SHoward Hinnant#include <system_error>
963e519524SHoward Hinnant#include <chrono>
973e519524SHoward Hinnant#include <__mutex_base>
988df61ea8SHoward Hinnant#ifndef _LIBCPP_HAS_NO_VARIADICS
998df61ea8SHoward Hinnant#include <tuple>
1008df61ea8SHoward Hinnant#endif
101c7e4239fSAsiri Rathnayake#include <__threading_support>
102ff94d250SEric Fiselier#include <__debug>
1033e519524SHoward Hinnant
104073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1053e519524SHoward Hinnant#pragma GCC system_header
106073458b1SHoward Hinnant#endif
1073e519524SHoward Hinnant
108e8e7af24SHoward Hinnant#define __STDCPP_THREADS__ __cplusplus
1093e519524SHoward Hinnant
110b3fcc67fSJonathan Roelofs#ifdef _LIBCPP_HAS_NO_THREADS
111b3fcc67fSJonathan Roelofs#error <thread> is not supported on this single threaded system
112b3fcc67fSJonathan Roelofs#else // !_LIBCPP_HAS_NO_THREADS
113b3fcc67fSJonathan Roelofs
1143e519524SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
1153e519524SHoward Hinnant
1164504cf2cSEric Fiseliertemplate <class _Tp> class __thread_specific_ptr;
1174504cf2cSEric Fiselierclass _LIBCPP_TYPE_VIS __thread_struct;
1184504cf2cSEric Fiselierclass _LIBCPP_HIDDEN __thread_struct_imp;
1194504cf2cSEric Fiselierclass __assoc_sub_state;
1204504cf2cSEric Fiselier
1214504cf2cSEric Fiselier_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1224504cf2cSEric Fiselier
1234504cf2cSEric Fiselierclass _LIBCPP_TYPE_VIS __thread_struct
1244504cf2cSEric Fiselier{
1254504cf2cSEric Fiselier    __thread_struct_imp* __p_;
1264504cf2cSEric Fiselier
1274504cf2cSEric Fiselier    __thread_struct(const __thread_struct&);
1284504cf2cSEric Fiselier    __thread_struct& operator=(const __thread_struct&);
1294504cf2cSEric Fiselierpublic:
1304504cf2cSEric Fiselier    __thread_struct();
1314504cf2cSEric Fiselier    ~__thread_struct();
1324504cf2cSEric Fiselier
1334504cf2cSEric Fiselier    void notify_all_at_thread_exit(condition_variable*, mutex*);
1344504cf2cSEric Fiselier    void __make_ready_at_thread_exit(__assoc_sub_state*);
1354504cf2cSEric Fiselier};
1364504cf2cSEric Fiselier
137167fd108SHoward Hinnanttemplate <class _Tp>
138167fd108SHoward Hinnantclass __thread_specific_ptr
139167fd108SHoward Hinnant{
1408c2bf45dSAsiri Rathnayake    __libcpp_tls_key __key_;
141167fd108SHoward Hinnant
1424504cf2cSEric Fiselier     // Only __thread_local_data() may construct a __thread_specific_ptr
1434504cf2cSEric Fiselier     // and only with _Tp == __thread_struct.
1449a5e62bfSEric Fiselier    static_assert((is_same<_Tp, __thread_struct>::value), "");
1454504cf2cSEric Fiselier    __thread_specific_ptr();
1464504cf2cSEric Fiselier    friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();
1474504cf2cSEric Fiselier
148167fd108SHoward Hinnant    __thread_specific_ptr(const __thread_specific_ptr&);
149167fd108SHoward Hinnant    __thread_specific_ptr& operator=(const __thread_specific_ptr&);
150167fd108SHoward Hinnant
1516d7d0becSSaleem Abdulrasool    static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
1526d7d0becSSaleem Abdulrasool
153167fd108SHoward Hinnantpublic:
154167fd108SHoward Hinnant    typedef _Tp* pointer;
155167fd108SHoward Hinnant
156167fd108SHoward Hinnant    ~__thread_specific_ptr();
157167fd108SHoward Hinnant
158e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
1598c2bf45dSAsiri Rathnayake    pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));}
160e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
161167fd108SHoward Hinnant    pointer operator*() const {return *get();}
162e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
163167fd108SHoward Hinnant    pointer operator->() const {return get();}
164ff94d250SEric Fiselier    void set_pointer(pointer __p);
165167fd108SHoward Hinnant};
166167fd108SHoward Hinnant
167167fd108SHoward Hinnanttemplate <class _Tp>
1686d7d0becSSaleem Abdulrasoolvoid _LIBCPP_TLS_DESTRUCTOR_CC
169167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)
170167fd108SHoward Hinnant{
171167fd108SHoward Hinnant    delete static_cast<pointer>(__p);
172167fd108SHoward Hinnant}
173167fd108SHoward Hinnant
174167fd108SHoward Hinnanttemplate <class _Tp>
175167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::__thread_specific_ptr()
176167fd108SHoward Hinnant{
1776d7d0becSSaleem Abdulrasool  int __ec =
1786d7d0becSSaleem Abdulrasool      __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);
179167fd108SHoward Hinnant  if (__ec)
1806d7d0becSSaleem Abdulrasool    __throw_system_error(__ec, "__thread_specific_ptr construction failed");
181167fd108SHoward Hinnant}
182167fd108SHoward Hinnant
183167fd108SHoward Hinnanttemplate <class _Tp>
184167fd108SHoward Hinnant__thread_specific_ptr<_Tp>::~__thread_specific_ptr()
185167fd108SHoward Hinnant{
1864504cf2cSEric Fiselier    // __thread_specific_ptr is only created with a static storage duration
1874504cf2cSEric Fiselier    // so this destructor is only invoked during program termination. Invoking
1884504cf2cSEric Fiselier    // pthread_key_delete(__key_) may prevent other threads from deleting their
1894504cf2cSEric Fiselier    // thread local data. For this reason we leak the key.
190167fd108SHoward Hinnant}
191167fd108SHoward Hinnant
192167fd108SHoward Hinnanttemplate <class _Tp>
193167fd108SHoward Hinnantvoid
194ff94d250SEric Fiselier__thread_specific_ptr<_Tp>::set_pointer(pointer __p)
195167fd108SHoward Hinnant{
196ff94d250SEric Fiselier    _LIBCPP_ASSERT(get() == nullptr,
197ff94d250SEric Fiselier                   "Attempting to overwrite thread local data");
1988c2bf45dSAsiri Rathnayake    __libcpp_tls_set(__key_, __p);
199167fd108SHoward Hinnant}
200167fd108SHoward Hinnant
2016e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS thread;
2026e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS __thread_id;
2033e519524SHoward Hinnant
2043e519524SHoward Hinnantnamespace this_thread
2053e519524SHoward Hinnant{
2063e519524SHoward Hinnant
207aeb85680SHoward Hinnant_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
2083e519524SHoward Hinnant
2093e519524SHoward Hinnant}  // this_thread
2103e519524SHoward Hinnant
21189dd1dd2SEric Fiseliertemplate<> struct hash<__thread_id>;
212f3d14a65SHoward Hinnant
213e2f2d1edSEric Fiselierclass _LIBCPP_TEMPLATE_VIS __thread_id
2143e519524SHoward Hinnant{
215128ba719SHoward Hinnant    // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
216128ba719SHoward Hinnant    // NULL is the no-thread value on Darwin.  Someone needs to check
217128ba719SHoward Hinnant    // on other platforms.  We assume 0 works everywhere for now.
218c7e4239fSAsiri Rathnayake    __libcpp_thread_id __id_;
2193e519524SHoward Hinnant
2203e519524SHoward Hinnantpublic:
221e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
22236101a5bSHoward Hinnant    __thread_id() _NOEXCEPT : __id_(0) {}
2233e519524SHoward Hinnant
224e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
22536101a5bSHoward Hinnant        bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
226c7e4239fSAsiri Rathnayake        {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);}
227e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
22836101a5bSHoward Hinnant        bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
2293e519524SHoward Hinnant        {return !(__x == __y);}
230e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
23136101a5bSHoward Hinnant        bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
232c7e4239fSAsiri Rathnayake        {return  __libcpp_thread_id_less(__x.__id_, __y.__id_);}
233e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
23436101a5bSHoward Hinnant        bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
2353e519524SHoward Hinnant        {return !(__y < __x);}
236e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
23736101a5bSHoward Hinnant        bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
2383e519524SHoward Hinnant        {return   __y < __x ;}
239e0601335SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
24036101a5bSHoward Hinnant        bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
2413e519524SHoward Hinnant        {return !(__x < __y);}
2423e519524SHoward Hinnant
2433e519524SHoward Hinnant    template<class _CharT, class _Traits>
2443e519524SHoward Hinnant    friend
245e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
2463e519524SHoward Hinnant    basic_ostream<_CharT, _Traits>&
2473e519524SHoward Hinnant    operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
2483e519524SHoward Hinnant        {return __os << __id.__id_;}
2493e519524SHoward Hinnant
2503e519524SHoward Hinnantprivate:
251e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
252c7e4239fSAsiri Rathnayake    __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
2533e519524SHoward Hinnant
254e4b2a743SHoward Hinnant    friend __thread_id this_thread::get_id() _NOEXCEPT;
2556e41256fSHoward Hinnant    friend class _LIBCPP_TYPE_VIS thread;
256e2f2d1edSEric Fiselier    friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
2573e519524SHoward Hinnant};
2583e519524SHoward Hinnant
2593e519524SHoward Hinnanttemplate<>
260e2f2d1edSEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
2613e519524SHoward Hinnant    : public unary_function<__thread_id, size_t>
2623e519524SHoward Hinnant{
263e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
2643e519524SHoward Hinnant    size_t operator()(__thread_id __v) const
2653e519524SHoward Hinnant    {
266c7e4239fSAsiri Rathnayake        return hash<__libcpp_thread_id>()(__v.__id_);
2673e519524SHoward Hinnant    }
2683e519524SHoward Hinnant};
2693e519524SHoward Hinnant
2703e519524SHoward Hinnantnamespace this_thread
2713e519524SHoward Hinnant{
2723e519524SHoward Hinnant
273e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
2743e519524SHoward Hinnant__thread_id
27536101a5bSHoward Hinnantget_id() _NOEXCEPT
2763e519524SHoward Hinnant{
277c7e4239fSAsiri Rathnayake    return __libcpp_thread_get_current_id();
2783e519524SHoward Hinnant}
2793e519524SHoward Hinnant
2803e519524SHoward Hinnant}  // this_thread
2813e519524SHoward Hinnant
2826e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS thread
2833e519524SHoward Hinnant{
284c7e4239fSAsiri Rathnayake    __libcpp_thread_t __t_;
2853e519524SHoward Hinnant
286eb269257SHoward Hinnant    thread(const thread&);
287eb269257SHoward Hinnant    thread& operator=(const thread&);
2883e519524SHoward Hinnantpublic:
2893e519524SHoward Hinnant    typedef __thread_id id;
290c7e4239fSAsiri Rathnayake    typedef __libcpp_thread_t native_handle_type;
2913e519524SHoward Hinnant
292e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
293af762e91SAsiri Rathnayake    thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {}
2943e519524SHoward Hinnant#ifndef _LIBCPP_HAS_NO_VARIADICS
295c003db1fSHoward Hinnant    template <class _Fp, class ..._Args,
2963e519524SHoward Hinnant              class = typename enable_if
2973e519524SHoward Hinnant              <
298c003db1fSHoward Hinnant                   !is_same<typename decay<_Fp>::type, thread>::value
2993e519524SHoward Hinnant              >::type
3003e519524SHoward Hinnant             >
301c003db1fSHoward Hinnant        explicit thread(_Fp&& __f, _Args&&... __args);
302b3371f6fSHoward Hinnant#else  // _LIBCPP_HAS_NO_VARIADICS
303c003db1fSHoward Hinnant    template <class _Fp> explicit thread(_Fp __f);
3043e519524SHoward Hinnant#endif
3053e519524SHoward Hinnant    ~thread();
3063e519524SHoward Hinnant
3077609c9b6SHoward Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
308e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
309af762e91SAsiri Rathnayake    thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;}
310906c872dSEvgeniy Stepanov    _LIBCPP_INLINE_VISIBILITY
31136101a5bSHoward Hinnant    thread& operator=(thread&& __t) _NOEXCEPT;
3127609c9b6SHoward Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
3133e519524SHoward Hinnant
314e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
31536101a5bSHoward Hinnant    void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);}
3163e519524SHoward Hinnant
317e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
318af762e91SAsiri Rathnayake    bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);}
3193e519524SHoward Hinnant    void join();
3203e519524SHoward Hinnant    void detach();
321e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
322c7e4239fSAsiri Rathnayake    id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);}
323e0601335SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
32436101a5bSHoward Hinnant    native_handle_type native_handle() _NOEXCEPT {return __t_;}
3253e519524SHoward Hinnant
32636101a5bSHoward Hinnant    static unsigned hardware_concurrency() _NOEXCEPT;
3273e519524SHoward Hinnant};
3283e519524SHoward Hinnant
3298df61ea8SHoward Hinnant#ifndef _LIBCPP_HAS_NO_VARIADICS
3308df61ea8SHoward Hinnant
331e08afaf8SEric Fiseliertemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices>
3328df61ea8SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
3338df61ea8SHoward Hinnantvoid
334e08afaf8SEric Fiselier__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>)
3358df61ea8SHoward Hinnant{
336e08afaf8SEric Fiselier    __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
3378df61ea8SHoward Hinnant}
3388df61ea8SHoward Hinnant
339c003db1fSHoward Hinnanttemplate <class _Fp>
340e08afaf8SEric Fiseliervoid* __thread_proxy(void* __vp)
3418df61ea8SHoward Hinnant{
342e08afaf8SEric Fiselier    // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...>
343c003db1fSHoward Hinnant    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
344ff94d250SEric Fiselier    __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release());
345e08afaf8SEric Fiselier    typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;
346ea48b6dcSHoward Hinnant    __thread_execute(*__p, _Index());
3478df61ea8SHoward Hinnant    return nullptr;
3488df61ea8SHoward Hinnant}
3498df61ea8SHoward Hinnant
350c003db1fSHoward Hinnanttemplate <class _Fp, class ..._Args,
3518df61ea8SHoward Hinnant          class
3528df61ea8SHoward Hinnant         >
353c003db1fSHoward Hinnantthread::thread(_Fp&& __f, _Args&&... __args)
3548df61ea8SHoward Hinnant{
355e08afaf8SEric Fiselier    typedef unique_ptr<__thread_struct> _TSPtr;
356e08afaf8SEric Fiselier    _TSPtr __tsp(new __thread_struct);
357e08afaf8SEric Fiselier    typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
358e08afaf8SEric Fiselier    _VSTD::unique_ptr<_Gp> __p(
359e08afaf8SEric Fiselier            new _Gp(std::move(__tsp),
360e08afaf8SEric Fiselier                    __decay_copy(_VSTD::forward<_Fp>(__f)),
361ce48a113SHoward Hinnant                    __decay_copy(_VSTD::forward<_Args>(__args))...));
362c7e4239fSAsiri Rathnayake    int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
3638df61ea8SHoward Hinnant    if (__ec == 0)
3648df61ea8SHoward Hinnant        __p.release();
3658df61ea8SHoward Hinnant    else
3668df61ea8SHoward Hinnant        __throw_system_error(__ec, "thread constructor failed");
3678df61ea8SHoward Hinnant}
3688df61ea8SHoward Hinnant
3698df61ea8SHoward Hinnant#else  // _LIBCPP_HAS_NO_VARIADICS
3708df61ea8SHoward Hinnant
371c003db1fSHoward Hinnanttemplate <class _Fp>
372e08afaf8SEric Fiselierstruct __thread_invoke_pair {
373e08afaf8SEric Fiselier    // This type is used to pass memory for thread local storage and a functor
374e08afaf8SEric Fiselier    // to a newly created thread because std::pair doesn't work with
375e08afaf8SEric Fiselier    // std::unique_ptr in C++03.
376e08afaf8SEric Fiselier    __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {}
377e08afaf8SEric Fiselier    unique_ptr<__thread_struct> __tsp_;
378e08afaf8SEric Fiselier    _Fp __fn_;
379e08afaf8SEric Fiselier};
380e08afaf8SEric Fiselier
381e08afaf8SEric Fiseliertemplate <class _Fp>
382e08afaf8SEric Fiseliervoid* __thread_proxy_cxx03(void* __vp)
3833e519524SHoward Hinnant{
384c003db1fSHoward Hinnant    std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));
385ff94d250SEric Fiselier    __thread_local_data().set_pointer(__p->__tsp_.release());
386e08afaf8SEric Fiselier    (__p->__fn_)();
3873e519524SHoward Hinnant    return nullptr;
3883e519524SHoward Hinnant}
3893e519524SHoward Hinnant
390c003db1fSHoward Hinnanttemplate <class _Fp>
391c003db1fSHoward Hinnantthread::thread(_Fp __f)
3923e519524SHoward Hinnant{
393e08afaf8SEric Fiselier
394e08afaf8SEric Fiselier    typedef __thread_invoke_pair<_Fp> _InvokePair;
395e08afaf8SEric Fiselier    typedef std::unique_ptr<_InvokePair> _PairPtr;
396e08afaf8SEric Fiselier    _PairPtr __pp(new _InvokePair(__f));
397c7e4239fSAsiri Rathnayake    int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get());
3983e519524SHoward Hinnant    if (__ec == 0)
399e08afaf8SEric Fiselier        __pp.release();
4003e519524SHoward Hinnant    else
4013e519524SHoward Hinnant        __throw_system_error(__ec, "thread constructor failed");
4023e519524SHoward Hinnant}
4033e519524SHoward Hinnant
404b3371f6fSHoward Hinnant#endif  // _LIBCPP_HAS_NO_VARIADICS
4053e519524SHoward Hinnant
4067609c9b6SHoward Hinnant#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
4073e519524SHoward Hinnant
408906c872dSEvgeniy Stepanovinline
4093e519524SHoward Hinnantthread&
41036101a5bSHoward Hinnantthread::operator=(thread&& __t) _NOEXCEPT
4113e519524SHoward Hinnant{
412af762e91SAsiri Rathnayake    if (!__libcpp_thread_isnull(&__t_))
4133e519524SHoward Hinnant        terminate();
4143e519524SHoward Hinnant    __t_ = __t.__t_;
415af762e91SAsiri Rathnayake    __t.__t_ = _LIBCPP_NULL_THREAD;
4163e519524SHoward Hinnant    return *this;
4173e519524SHoward Hinnant}
4183e519524SHoward Hinnant
4197609c9b6SHoward Hinnant#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
4203e519524SHoward Hinnant
421e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
42236101a5bSHoward Hinnantvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);}
4233e519524SHoward Hinnant
4243e519524SHoward Hinnantnamespace this_thread
4253e519524SHoward Hinnant{
4263e519524SHoward Hinnant
427*9e8a082dSJoerg Sonnenberger_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns);
4283e519524SHoward Hinnant
4293e519524SHoward Hinnanttemplate <class _Rep, class _Period>
4303e519524SHoward Hinnantvoid
4313e519524SHoward Hinnantsleep_for(const chrono::duration<_Rep, _Period>& __d)
4323e519524SHoward Hinnant{
4333e519524SHoward Hinnant    using namespace chrono;
434aad745a0SHoward Hinnant    if (__d > duration<_Rep, _Period>::zero())
435aad745a0SHoward Hinnant    {
436aad745a0SHoward Hinnant        _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max();
437aad745a0SHoward Hinnant        nanoseconds __ns;
438aad745a0SHoward Hinnant        if (__d < _Max)
439aad745a0SHoward Hinnant        {
440aad745a0SHoward Hinnant            __ns = duration_cast<nanoseconds>(__d);
4413e519524SHoward Hinnant            if (__ns < __d)
4423e519524SHoward Hinnant                ++__ns;
443aad745a0SHoward Hinnant        }
444aad745a0SHoward Hinnant        else
445aad745a0SHoward Hinnant            __ns = nanoseconds::max();
4463e519524SHoward Hinnant        sleep_for(__ns);
4473e519524SHoward Hinnant    }
448aad745a0SHoward Hinnant}
4493e519524SHoward Hinnant
4503e519524SHoward Hinnanttemplate <class _Clock, class _Duration>
4513e519524SHoward Hinnantvoid
4523e519524SHoward Hinnantsleep_until(const chrono::time_point<_Clock, _Duration>& __t)
4533e519524SHoward Hinnant{
4543e519524SHoward Hinnant    using namespace chrono;
4553e519524SHoward Hinnant    mutex __mut;
4563e519524SHoward Hinnant    condition_variable __cv;
4573e519524SHoward Hinnant    unique_lock<mutex> __lk(__mut);
4583e519524SHoward Hinnant    while (_Clock::now() < __t)
4593e519524SHoward Hinnant        __cv.wait_until(__lk, __t);
4603e519524SHoward Hinnant}
4613e519524SHoward Hinnant
4623e519524SHoward Hinnanttemplate <class _Duration>
463e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
4643e519524SHoward Hinnantvoid
4653dc6455fSHoward Hinnantsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
4663e519524SHoward Hinnant{
4673e519524SHoward Hinnant    using namespace chrono;
4683dc6455fSHoward Hinnant    sleep_for(__t - steady_clock::now());
4693e519524SHoward Hinnant}
4703e519524SHoward Hinnant
471e0601335SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
472c7e4239fSAsiri Rathnayakevoid yield() _NOEXCEPT {__libcpp_thread_yield();}
4733e519524SHoward Hinnant
4743e519524SHoward Hinnant}  // this_thread
4753e519524SHoward Hinnant
4763e519524SHoward Hinnant_LIBCPP_END_NAMESPACE_STD
4773e519524SHoward Hinnant
478b3fcc67fSJonathan Roelofs#endif // !_LIBCPP_HAS_NO_THREADS
479b3fcc67fSJonathan Roelofs
4803e519524SHoward Hinnant#endif  // _LIBCPP_THREAD
481