10b57cec5SDimitry Andric// -*- C++ -*- 2*349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_THREAD 110b57cec5SDimitry Andric#define _LIBCPP_THREAD 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric thread synopsis 160b57cec5SDimitry Andric 170b57cec5SDimitry Andricnamespace std 180b57cec5SDimitry Andric{ 190b57cec5SDimitry Andric 200b57cec5SDimitry Andricclass thread 210b57cec5SDimitry Andric{ 220b57cec5SDimitry Andricpublic: 230b57cec5SDimitry Andric class id; 240b57cec5SDimitry Andric typedef pthread_t native_handle_type; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric thread() noexcept; 270b57cec5SDimitry Andric template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 280b57cec5SDimitry Andric ~thread(); 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric thread(const thread&) = delete; 310b57cec5SDimitry Andric thread(thread&& t) noexcept; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric thread& operator=(const thread&) = delete; 340b57cec5SDimitry Andric thread& operator=(thread&& t) noexcept; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void swap(thread& t) noexcept; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool joinable() const noexcept; 390b57cec5SDimitry Andric void join(); 400b57cec5SDimitry Andric void detach(); 410b57cec5SDimitry Andric id get_id() const noexcept; 420b57cec5SDimitry Andric native_handle_type native_handle(); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric static unsigned hardware_concurrency() noexcept; 450b57cec5SDimitry Andric}; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andricvoid swap(thread& x, thread& y) noexcept; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andricclass thread::id 500b57cec5SDimitry Andric{ 510b57cec5SDimitry Andricpublic: 520b57cec5SDimitry Andric id() noexcept; 530b57cec5SDimitry Andric}; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andricbool operator==(thread::id x, thread::id y) noexcept; 560b57cec5SDimitry Andricbool operator!=(thread::id x, thread::id y) noexcept; 570b57cec5SDimitry Andricbool operator< (thread::id x, thread::id y) noexcept; 580b57cec5SDimitry Andricbool operator<=(thread::id x, thread::id y) noexcept; 590b57cec5SDimitry Andricbool operator> (thread::id x, thread::id y) noexcept; 600b57cec5SDimitry Andricbool operator>=(thread::id x, thread::id y) noexcept; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andrictemplate<class charT, class traits> 630b57cec5SDimitry Andricbasic_ostream<charT, traits>& 640b57cec5SDimitry Andricoperator<<(basic_ostream<charT, traits>& out, thread::id id); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andricnamespace this_thread 670b57cec5SDimitry Andric{ 680b57cec5SDimitry Andric 690b57cec5SDimitry Andricthread::id get_id() noexcept; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andricvoid yield() noexcept; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andrictemplate <class Clock, class Duration> 740b57cec5SDimitry Andricvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andrictemplate <class Rep, class Period> 770b57cec5SDimitry Andricvoid sleep_for(const chrono::duration<Rep, Period>& rel_time); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric} // this_thread 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric} // std 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric*/ 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric#include <__config> 86fe6060f1SDimitry Andric#include <__debug> 870b57cec5SDimitry Andric#include <__functional_base> 88fe6060f1SDimitry Andric#include <__mutex_base> 89*349cc55cSDimitry Andric#include <__thread/poll_with_backoff.h> 90fe6060f1SDimitry Andric#include <__threading_support> 91*349cc55cSDimitry Andric#include <__utility/decay_copy.h> 92fe6060f1SDimitry Andric#include <__utility/forward.h> 93fe6060f1SDimitry Andric#include <chrono> 940b57cec5SDimitry Andric#include <cstddef> 950b57cec5SDimitry Andric#include <functional> 96fe6060f1SDimitry Andric#include <iosfwd> 970b57cec5SDimitry Andric#include <memory> 980b57cec5SDimitry Andric#include <system_error> 990b57cec5SDimitry Andric#include <tuple> 100fe6060f1SDimitry Andric#include <type_traits> 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1030b57cec5SDimitry Andric#pragma GCC system_header 1040b57cec5SDimitry Andric#endif 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS 1070b57cec5SDimitry Andric#include <__undef_macros> 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric#ifdef _LIBCPP_HAS_NO_THREADS 1100b57cec5SDimitry Andric#error <thread> is not supported on this single threaded system 1110b57cec5SDimitry Andric#else // !_LIBCPP_HAS_NO_THREADS 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andrictemplate <class _Tp> class __thread_specific_ptr; 1160b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct; 1170b57cec5SDimitry Andricclass _LIBCPP_HIDDEN __thread_struct_imp; 1180b57cec5SDimitry Andricclass __assoc_sub_state; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct 1230b57cec5SDimitry Andric{ 1240b57cec5SDimitry Andric __thread_struct_imp* __p_; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric __thread_struct(const __thread_struct&); 1270b57cec5SDimitry Andric __thread_struct& operator=(const __thread_struct&); 1280b57cec5SDimitry Andricpublic: 1290b57cec5SDimitry Andric __thread_struct(); 1300b57cec5SDimitry Andric ~__thread_struct(); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric void notify_all_at_thread_exit(condition_variable*, mutex*); 1330b57cec5SDimitry Andric void __make_ready_at_thread_exit(__assoc_sub_state*); 1340b57cec5SDimitry Andric}; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andrictemplate <class _Tp> 1370b57cec5SDimitry Andricclass __thread_specific_ptr 1380b57cec5SDimitry Andric{ 1390b57cec5SDimitry Andric __libcpp_tls_key __key_; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Only __thread_local_data() may construct a __thread_specific_ptr 1420b57cec5SDimitry Andric // and only with _Tp == __thread_struct. 1430b57cec5SDimitry Andric static_assert((is_same<_Tp, __thread_struct>::value), ""); 1440b57cec5SDimitry Andric __thread_specific_ptr(); 1450b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric __thread_specific_ptr(const __thread_specific_ptr&); 1480b57cec5SDimitry Andric __thread_specific_ptr& operator=(const __thread_specific_ptr&); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andricpublic: 1530b57cec5SDimitry Andric typedef _Tp* pointer; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric ~__thread_specific_ptr(); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1580b57cec5SDimitry Andric pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} 1590b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1600b57cec5SDimitry Andric pointer operator*() const {return *get();} 1610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1620b57cec5SDimitry Andric pointer operator->() const {return get();} 1630b57cec5SDimitry Andric void set_pointer(pointer __p); 1640b57cec5SDimitry Andric}; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andrictemplate <class _Tp> 1670b57cec5SDimitry Andricvoid _LIBCPP_TLS_DESTRUCTOR_CC 1680b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 1690b57cec5SDimitry Andric{ 1700b57cec5SDimitry Andric delete static_cast<pointer>(__p); 1710b57cec5SDimitry Andric} 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andrictemplate <class _Tp> 1740b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::__thread_specific_ptr() 1750b57cec5SDimitry Andric{ 1760b57cec5SDimitry Andric int __ec = 1770b57cec5SDimitry Andric __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 1780b57cec5SDimitry Andric if (__ec) 1790b57cec5SDimitry Andric __throw_system_error(__ec, "__thread_specific_ptr construction failed"); 1800b57cec5SDimitry Andric} 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andrictemplate <class _Tp> 1830b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 1840b57cec5SDimitry Andric{ 1850b57cec5SDimitry Andric // __thread_specific_ptr is only created with a static storage duration 1860b57cec5SDimitry Andric // so this destructor is only invoked during program termination. Invoking 1870b57cec5SDimitry Andric // pthread_key_delete(__key_) may prevent other threads from deleting their 1880b57cec5SDimitry Andric // thread local data. For this reason we leak the key. 1890b57cec5SDimitry Andric} 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andrictemplate <class _Tp> 1920b57cec5SDimitry Andricvoid 1930b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::set_pointer(pointer __p) 1940b57cec5SDimitry Andric{ 1950b57cec5SDimitry Andric _LIBCPP_ASSERT(get() == nullptr, 1960b57cec5SDimitry Andric "Attempting to overwrite thread local data"); 1970b57cec5SDimitry Andric __libcpp_tls_set(__key_, __p); 1980b57cec5SDimitry Andric} 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andrictemplate<> 2010b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id> 2020b57cec5SDimitry Andric : public unary_function<__thread_id, size_t> 2030b57cec5SDimitry Andric{ 2040b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2050b57cec5SDimitry Andric size_t operator()(__thread_id __v) const _NOEXCEPT 2060b57cec5SDimitry Andric { 2070b57cec5SDimitry Andric return hash<__libcpp_thread_id>()(__v.__id_); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric}; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andrictemplate<class _CharT, class _Traits> 2120b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY 2130b57cec5SDimitry Andricbasic_ostream<_CharT, _Traits>& 2140b57cec5SDimitry Andricoperator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 2150b57cec5SDimitry Andric{return __os << __id.__id_;} 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS thread 2180b57cec5SDimitry Andric{ 2190b57cec5SDimitry Andric __libcpp_thread_t __t_; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric thread(const thread&); 2220b57cec5SDimitry Andric thread& operator=(const thread&); 2230b57cec5SDimitry Andricpublic: 2240b57cec5SDimitry Andric typedef __thread_id id; 2250b57cec5SDimitry Andric typedef __libcpp_thread_t native_handle_type; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2280b57cec5SDimitry Andric thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} 2290b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 2300b57cec5SDimitry Andric template <class _Fp, class ..._Args, 2310b57cec5SDimitry Andric class = typename enable_if 2320b57cec5SDimitry Andric < 2330b57cec5SDimitry Andric !is_same<typename __uncvref<_Fp>::type, thread>::value 2340b57cec5SDimitry Andric >::type 2350b57cec5SDimitry Andric > 2360b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2370b57cec5SDimitry Andric explicit thread(_Fp&& __f, _Args&&... __args); 2380b57cec5SDimitry Andric#else // _LIBCPP_CXX03_LANG 2390b57cec5SDimitry Andric template <class _Fp> 2400b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2410b57cec5SDimitry Andric explicit thread(_Fp __f); 2420b57cec5SDimitry Andric#endif 2430b57cec5SDimitry Andric ~thread(); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2465ffd83dbSDimitry Andric thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { 2475ffd83dbSDimitry Andric __t.__t_ = _LIBCPP_NULL_THREAD; 2485ffd83dbSDimitry Andric } 2495ffd83dbSDimitry Andric 2500b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2515ffd83dbSDimitry Andric thread& operator=(thread&& __t) _NOEXCEPT { 2525ffd83dbSDimitry Andric if (!__libcpp_thread_isnull(&__t_)) 2535ffd83dbSDimitry Andric terminate(); 2545ffd83dbSDimitry Andric __t_ = __t.__t_; 2555ffd83dbSDimitry Andric __t.__t_ = _LIBCPP_NULL_THREAD; 2565ffd83dbSDimitry Andric return *this; 2575ffd83dbSDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2600b57cec5SDimitry Andric void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2630b57cec5SDimitry Andric bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} 2640b57cec5SDimitry Andric void join(); 2650b57cec5SDimitry Andric void detach(); 2660b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2670b57cec5SDimitry Andric id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} 2680b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2690b57cec5SDimitry Andric native_handle_type native_handle() _NOEXCEPT {return __t_;} 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric static unsigned hardware_concurrency() _NOEXCEPT; 2720b57cec5SDimitry Andric}; 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andrictemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> 2770b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 2780b57cec5SDimitry Andricvoid 2790b57cec5SDimitry Andric__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) 2800b57cec5SDimitry Andric{ 281e8d8bef9SDimitry Andric _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 2820b57cec5SDimitry Andric} 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andrictemplate <class _Fp> 285480093f4SDimitry Andric_LIBCPP_INLINE_VISIBILITY 2860b57cec5SDimitry Andricvoid* __thread_proxy(void* __vp) 2870b57cec5SDimitry Andric{ 288e8d8bef9SDimitry Andric // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> 289e8d8bef9SDimitry Andric unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 290e8d8bef9SDimitry Andric __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release()); 2910b57cec5SDimitry Andric typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; 292e8d8bef9SDimitry Andric _VSTD::__thread_execute(*__p.get(), _Index()); 2930b57cec5SDimitry Andric return nullptr; 2940b57cec5SDimitry Andric} 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andrictemplate <class _Fp, class ..._Args, 2970b57cec5SDimitry Andric class 2980b57cec5SDimitry Andric > 2990b57cec5SDimitry Andricthread::thread(_Fp&& __f, _Args&&... __args) 3000b57cec5SDimitry Andric{ 3010b57cec5SDimitry Andric typedef unique_ptr<__thread_struct> _TSPtr; 3020b57cec5SDimitry Andric _TSPtr __tsp(new __thread_struct); 3030b57cec5SDimitry Andric typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 304e8d8bef9SDimitry Andric unique_ptr<_Gp> __p( 305e8d8bef9SDimitry Andric new _Gp(_VSTD::move(__tsp), 306e8d8bef9SDimitry Andric _VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)), 307e8d8bef9SDimitry Andric _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...)); 308e8d8bef9SDimitry Andric int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); 3090b57cec5SDimitry Andric if (__ec == 0) 3100b57cec5SDimitry Andric __p.release(); 3110b57cec5SDimitry Andric else 3120b57cec5SDimitry Andric __throw_system_error(__ec, "thread constructor failed"); 3130b57cec5SDimitry Andric} 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric#else // _LIBCPP_CXX03_LANG 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andrictemplate <class _Fp> 3180b57cec5SDimitry Andricstruct __thread_invoke_pair { 3190b57cec5SDimitry Andric // This type is used to pass memory for thread local storage and a functor 3200b57cec5SDimitry Andric // to a newly created thread because std::pair doesn't work with 3210b57cec5SDimitry Andric // std::unique_ptr in C++03. 3220b57cec5SDimitry Andric __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} 3230b57cec5SDimitry Andric unique_ptr<__thread_struct> __tsp_; 3240b57cec5SDimitry Andric _Fp __fn_; 3250b57cec5SDimitry Andric}; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andrictemplate <class _Fp> 3280b57cec5SDimitry Andricvoid* __thread_proxy_cxx03(void* __vp) 3290b57cec5SDimitry Andric{ 330e8d8bef9SDimitry Andric unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 3310b57cec5SDimitry Andric __thread_local_data().set_pointer(__p->__tsp_.release()); 3320b57cec5SDimitry Andric (__p->__fn_)(); 3330b57cec5SDimitry Andric return nullptr; 3340b57cec5SDimitry Andric} 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andrictemplate <class _Fp> 3370b57cec5SDimitry Andricthread::thread(_Fp __f) 3380b57cec5SDimitry Andric{ 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric typedef __thread_invoke_pair<_Fp> _InvokePair; 341e8d8bef9SDimitry Andric typedef unique_ptr<_InvokePair> _PairPtr; 3420b57cec5SDimitry Andric _PairPtr __pp(new _InvokePair(__f)); 343e8d8bef9SDimitry Andric int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); 3440b57cec5SDimitry Andric if (__ec == 0) 3450b57cec5SDimitry Andric __pp.release(); 3460b57cec5SDimitry Andric else 3470b57cec5SDimitry Andric __throw_system_error(__ec, "thread constructor failed"); 3480b57cec5SDimitry Andric} 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3530b57cec5SDimitry Andricvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andricnamespace this_thread 3560b57cec5SDimitry Andric{ 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andrictemplate <class _Rep, class _Period> 3610b57cec5SDimitry Andricvoid 3620b57cec5SDimitry Andricsleep_for(const chrono::duration<_Rep, _Period>& __d) 3630b57cec5SDimitry Andric{ 364e8d8bef9SDimitry Andric if (__d > chrono::duration<_Rep, _Period>::zero()) 3650b57cec5SDimitry Andric { 366fe6060f1SDimitry Andric // The standard guarantees a 64bit signed integer resolution for nanoseconds, 367fe6060f1SDimitry Andric // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> 368fe6060f1SDimitry Andric // and issues with long double folding on PowerPC with GCC. 369fe6060f1SDimitry Andric _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = 370fe6060f1SDimitry Andric chrono::duration<long double>(9223372036.0L); 371e8d8bef9SDimitry Andric chrono::nanoseconds __ns; 3720b57cec5SDimitry Andric if (__d < _Max) 3730b57cec5SDimitry Andric { 374e8d8bef9SDimitry Andric __ns = chrono::duration_cast<chrono::nanoseconds>(__d); 3750b57cec5SDimitry Andric if (__ns < __d) 3760b57cec5SDimitry Andric ++__ns; 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric else 379e8d8bef9SDimitry Andric __ns = chrono::nanoseconds::max(); 380e8d8bef9SDimitry Andric this_thread::sleep_for(__ns); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric} 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andrictemplate <class _Clock, class _Duration> 3850b57cec5SDimitry Andricvoid 3860b57cec5SDimitry Andricsleep_until(const chrono::time_point<_Clock, _Duration>& __t) 3870b57cec5SDimitry Andric{ 3880b57cec5SDimitry Andric mutex __mut; 3890b57cec5SDimitry Andric condition_variable __cv; 3900b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut); 3910b57cec5SDimitry Andric while (_Clock::now() < __t) 3920b57cec5SDimitry Andric __cv.wait_until(__lk, __t); 3930b57cec5SDimitry Andric} 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andrictemplate <class _Duration> 3960b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3970b57cec5SDimitry Andricvoid 3980b57cec5SDimitry Andricsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 3990b57cec5SDimitry Andric{ 400e8d8bef9SDimitry Andric this_thread::sleep_for(__t - chrono::steady_clock::now()); 4010b57cec5SDimitry Andric} 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4040b57cec5SDimitry Andricvoid yield() _NOEXCEPT {__libcpp_thread_yield();} 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric} // this_thread 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric_LIBCPP_POP_MACROS 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric#endif // _LIBCPP_THREAD 415