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