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