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