10b57cec5SDimitry Andric// -*- C++ -*- 2349cc55cSDimitry 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> 89349cc55cSDimitry Andric#include <__thread/poll_with_backoff.h> 90*04eeddc0SDimitry Andric#include <__thread/timed_backoff_policy.h> 91fe6060f1SDimitry Andric#include <__threading_support> 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> 101*04eeddc0SDimitry Andric#include <version> 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1040b57cec5SDimitry Andric#pragma GCC system_header 1050b57cec5SDimitry Andric#endif 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS 1080b57cec5SDimitry Andric#include <__undef_macros> 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric#ifdef _LIBCPP_HAS_NO_THREADS 1110b57cec5SDimitry Andric#error <thread> is not supported on this single threaded system 1120b57cec5SDimitry Andric#else // !_LIBCPP_HAS_NO_THREADS 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andrictemplate <class _Tp> class __thread_specific_ptr; 1170b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct; 1180b57cec5SDimitry Andricclass _LIBCPP_HIDDEN __thread_struct_imp; 1190b57cec5SDimitry Andricclass __assoc_sub_state; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS __thread_struct 1240b57cec5SDimitry Andric{ 1250b57cec5SDimitry Andric __thread_struct_imp* __p_; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric __thread_struct(const __thread_struct&); 1280b57cec5SDimitry Andric __thread_struct& operator=(const __thread_struct&); 1290b57cec5SDimitry Andricpublic: 1300b57cec5SDimitry Andric __thread_struct(); 1310b57cec5SDimitry Andric ~__thread_struct(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric void notify_all_at_thread_exit(condition_variable*, mutex*); 1340b57cec5SDimitry Andric void __make_ready_at_thread_exit(__assoc_sub_state*); 1350b57cec5SDimitry Andric}; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andrictemplate <class _Tp> 1380b57cec5SDimitry Andricclass __thread_specific_ptr 1390b57cec5SDimitry Andric{ 1400b57cec5SDimitry Andric __libcpp_tls_key __key_; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Only __thread_local_data() may construct a __thread_specific_ptr 1430b57cec5SDimitry Andric // and only with _Tp == __thread_struct. 1440b57cec5SDimitry Andric static_assert((is_same<_Tp, __thread_struct>::value), ""); 1450b57cec5SDimitry Andric __thread_specific_ptr(); 1460b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric __thread_specific_ptr(const __thread_specific_ptr&); 1490b57cec5SDimitry Andric __thread_specific_ptr& operator=(const __thread_specific_ptr&); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andricpublic: 1540b57cec5SDimitry Andric typedef _Tp* pointer; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric ~__thread_specific_ptr(); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1590b57cec5SDimitry Andric pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} 1600b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1610b57cec5SDimitry Andric pointer operator*() const {return *get();} 1620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 1630b57cec5SDimitry Andric pointer operator->() const {return get();} 1640b57cec5SDimitry Andric void set_pointer(pointer __p); 1650b57cec5SDimitry Andric}; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andrictemplate <class _Tp> 1680b57cec5SDimitry Andricvoid _LIBCPP_TLS_DESTRUCTOR_CC 1690b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 1700b57cec5SDimitry Andric{ 1710b57cec5SDimitry Andric delete static_cast<pointer>(__p); 1720b57cec5SDimitry Andric} 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andrictemplate <class _Tp> 1750b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::__thread_specific_ptr() 1760b57cec5SDimitry Andric{ 1770b57cec5SDimitry Andric int __ec = 1780b57cec5SDimitry Andric __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 1790b57cec5SDimitry Andric if (__ec) 1800b57cec5SDimitry Andric __throw_system_error(__ec, "__thread_specific_ptr construction failed"); 1810b57cec5SDimitry Andric} 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andrictemplate <class _Tp> 1840b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 1850b57cec5SDimitry Andric{ 1860b57cec5SDimitry Andric // __thread_specific_ptr is only created with a static storage duration 1870b57cec5SDimitry Andric // so this destructor is only invoked during program termination. Invoking 1880b57cec5SDimitry Andric // pthread_key_delete(__key_) may prevent other threads from deleting their 1890b57cec5SDimitry Andric // thread local data. For this reason we leak the key. 1900b57cec5SDimitry Andric} 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andrictemplate <class _Tp> 1930b57cec5SDimitry Andricvoid 1940b57cec5SDimitry Andric__thread_specific_ptr<_Tp>::set_pointer(pointer __p) 1950b57cec5SDimitry Andric{ 1960b57cec5SDimitry Andric _LIBCPP_ASSERT(get() == nullptr, 1970b57cec5SDimitry Andric "Attempting to overwrite thread local data"); 1980b57cec5SDimitry Andric __libcpp_tls_set(__key_, __p); 1990b57cec5SDimitry Andric} 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andrictemplate<> 2020b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<__thread_id> 2030b57cec5SDimitry Andric : public unary_function<__thread_id, size_t> 2040b57cec5SDimitry Andric{ 2050b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2060b57cec5SDimitry Andric size_t operator()(__thread_id __v) const _NOEXCEPT 2070b57cec5SDimitry Andric { 2080b57cec5SDimitry Andric return hash<__libcpp_thread_id>()(__v.__id_); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric}; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andrictemplate<class _CharT, class _Traits> 2130b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY 2140b57cec5SDimitry Andricbasic_ostream<_CharT, _Traits>& 2150b57cec5SDimitry Andricoperator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 2160b57cec5SDimitry Andric{return __os << __id.__id_;} 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS thread 2190b57cec5SDimitry Andric{ 2200b57cec5SDimitry Andric __libcpp_thread_t __t_; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric thread(const thread&); 2230b57cec5SDimitry Andric thread& operator=(const thread&); 2240b57cec5SDimitry Andricpublic: 2250b57cec5SDimitry Andric typedef __thread_id id; 2260b57cec5SDimitry Andric typedef __libcpp_thread_t native_handle_type; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2290b57cec5SDimitry Andric thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} 2300b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 2310b57cec5SDimitry Andric template <class _Fp, class ..._Args, 2320b57cec5SDimitry Andric class = typename enable_if 2330b57cec5SDimitry Andric < 2340b57cec5SDimitry Andric !is_same<typename __uncvref<_Fp>::type, thread>::value 2350b57cec5SDimitry Andric >::type 2360b57cec5SDimitry Andric > 2370b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2380b57cec5SDimitry Andric explicit thread(_Fp&& __f, _Args&&... __args); 2390b57cec5SDimitry Andric#else // _LIBCPP_CXX03_LANG 2400b57cec5SDimitry Andric template <class _Fp> 2410b57cec5SDimitry Andric _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 2420b57cec5SDimitry Andric explicit thread(_Fp __f); 2430b57cec5SDimitry Andric#endif 2440b57cec5SDimitry Andric ~thread(); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2475ffd83dbSDimitry Andric thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { 2485ffd83dbSDimitry Andric __t.__t_ = _LIBCPP_NULL_THREAD; 2495ffd83dbSDimitry Andric } 2505ffd83dbSDimitry Andric 2510b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2525ffd83dbSDimitry Andric thread& operator=(thread&& __t) _NOEXCEPT { 2535ffd83dbSDimitry Andric if (!__libcpp_thread_isnull(&__t_)) 2545ffd83dbSDimitry Andric terminate(); 2555ffd83dbSDimitry Andric __t_ = __t.__t_; 2565ffd83dbSDimitry Andric __t.__t_ = _LIBCPP_NULL_THREAD; 2575ffd83dbSDimitry Andric return *this; 2585ffd83dbSDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2610b57cec5SDimitry Andric void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2640b57cec5SDimitry Andric bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} 2650b57cec5SDimitry Andric void join(); 2660b57cec5SDimitry Andric void detach(); 2670b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2680b57cec5SDimitry Andric id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} 2690b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2700b57cec5SDimitry Andric native_handle_type native_handle() _NOEXCEPT {return __t_;} 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric static unsigned hardware_concurrency() _NOEXCEPT; 2730b57cec5SDimitry Andric}; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andrictemplate <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> 2780b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 2790b57cec5SDimitry Andricvoid 2800b57cec5SDimitry Andric__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) 2810b57cec5SDimitry Andric{ 282e8d8bef9SDimitry Andric _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 2830b57cec5SDimitry Andric} 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andrictemplate <class _Fp> 286480093f4SDimitry Andric_LIBCPP_INLINE_VISIBILITY 2870b57cec5SDimitry Andricvoid* __thread_proxy(void* __vp) 2880b57cec5SDimitry Andric{ 289e8d8bef9SDimitry Andric // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> 290e8d8bef9SDimitry Andric unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 291e8d8bef9SDimitry Andric __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release()); 2920b57cec5SDimitry Andric typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; 293e8d8bef9SDimitry Andric _VSTD::__thread_execute(*__p.get(), _Index()); 2940b57cec5SDimitry Andric return nullptr; 2950b57cec5SDimitry Andric} 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andrictemplate <class _Fp, class ..._Args, 2980b57cec5SDimitry Andric class 2990b57cec5SDimitry Andric > 3000b57cec5SDimitry Andricthread::thread(_Fp&& __f, _Args&&... __args) 3010b57cec5SDimitry Andric{ 3020b57cec5SDimitry Andric typedef unique_ptr<__thread_struct> _TSPtr; 3030b57cec5SDimitry Andric _TSPtr __tsp(new __thread_struct); 3040b57cec5SDimitry Andric typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 305e8d8bef9SDimitry Andric unique_ptr<_Gp> __p( 306e8d8bef9SDimitry Andric new _Gp(_VSTD::move(__tsp), 3070eae32dcSDimitry Andric _VSTD::forward<_Fp>(__f), 3080eae32dcSDimitry Andric _VSTD::forward<_Args>(__args)...)); 309e8d8bef9SDimitry Andric int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); 3100b57cec5SDimitry Andric if (__ec == 0) 3110b57cec5SDimitry Andric __p.release(); 3120b57cec5SDimitry Andric else 3130b57cec5SDimitry Andric __throw_system_error(__ec, "thread constructor failed"); 3140b57cec5SDimitry Andric} 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric#else // _LIBCPP_CXX03_LANG 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andrictemplate <class _Fp> 3190b57cec5SDimitry Andricstruct __thread_invoke_pair { 3200b57cec5SDimitry Andric // This type is used to pass memory for thread local storage and a functor 3210b57cec5SDimitry Andric // to a newly created thread because std::pair doesn't work with 3220b57cec5SDimitry Andric // std::unique_ptr in C++03. 3230b57cec5SDimitry Andric __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} 3240b57cec5SDimitry Andric unique_ptr<__thread_struct> __tsp_; 3250b57cec5SDimitry Andric _Fp __fn_; 3260b57cec5SDimitry Andric}; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andrictemplate <class _Fp> 3290b57cec5SDimitry Andricvoid* __thread_proxy_cxx03(void* __vp) 3300b57cec5SDimitry Andric{ 331e8d8bef9SDimitry Andric unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 3320b57cec5SDimitry Andric __thread_local_data().set_pointer(__p->__tsp_.release()); 3330b57cec5SDimitry Andric (__p->__fn_)(); 3340b57cec5SDimitry Andric return nullptr; 3350b57cec5SDimitry Andric} 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andrictemplate <class _Fp> 3380b57cec5SDimitry Andricthread::thread(_Fp __f) 3390b57cec5SDimitry Andric{ 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric typedef __thread_invoke_pair<_Fp> _InvokePair; 342e8d8bef9SDimitry Andric typedef unique_ptr<_InvokePair> _PairPtr; 3430b57cec5SDimitry Andric _PairPtr __pp(new _InvokePair(__f)); 344e8d8bef9SDimitry Andric int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); 3450b57cec5SDimitry Andric if (__ec == 0) 3460b57cec5SDimitry Andric __pp.release(); 3470b57cec5SDimitry Andric else 3480b57cec5SDimitry Andric __throw_system_error(__ec, "thread constructor failed"); 3490b57cec5SDimitry Andric} 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3540b57cec5SDimitry Andricvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andricnamespace this_thread 3570b57cec5SDimitry Andric{ 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andrictemplate <class _Rep, class _Period> 3620b57cec5SDimitry Andricvoid 3630b57cec5SDimitry Andricsleep_for(const chrono::duration<_Rep, _Period>& __d) 3640b57cec5SDimitry Andric{ 365e8d8bef9SDimitry Andric if (__d > chrono::duration<_Rep, _Period>::zero()) 3660b57cec5SDimitry Andric { 367fe6060f1SDimitry Andric // The standard guarantees a 64bit signed integer resolution for nanoseconds, 368fe6060f1SDimitry Andric // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> 369fe6060f1SDimitry Andric // and issues with long double folding on PowerPC with GCC. 370fe6060f1SDimitry Andric _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = 371fe6060f1SDimitry Andric chrono::duration<long double>(9223372036.0L); 372e8d8bef9SDimitry Andric chrono::nanoseconds __ns; 3730b57cec5SDimitry Andric if (__d < _Max) 3740b57cec5SDimitry Andric { 375e8d8bef9SDimitry Andric __ns = chrono::duration_cast<chrono::nanoseconds>(__d); 3760b57cec5SDimitry Andric if (__ns < __d) 3770b57cec5SDimitry Andric ++__ns; 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric else 380e8d8bef9SDimitry Andric __ns = chrono::nanoseconds::max(); 381e8d8bef9SDimitry Andric this_thread::sleep_for(__ns); 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric} 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andrictemplate <class _Clock, class _Duration> 3860b57cec5SDimitry Andricvoid 3870b57cec5SDimitry Andricsleep_until(const chrono::time_point<_Clock, _Duration>& __t) 3880b57cec5SDimitry Andric{ 3890b57cec5SDimitry Andric mutex __mut; 3900b57cec5SDimitry Andric condition_variable __cv; 3910b57cec5SDimitry Andric unique_lock<mutex> __lk(__mut); 3920b57cec5SDimitry Andric while (_Clock::now() < __t) 3930b57cec5SDimitry Andric __cv.wait_until(__lk, __t); 3940b57cec5SDimitry Andric} 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andrictemplate <class _Duration> 3970b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3980b57cec5SDimitry Andricvoid 3990b57cec5SDimitry Andricsleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 4000b57cec5SDimitry Andric{ 401e8d8bef9SDimitry Andric this_thread::sleep_for(__t - chrono::steady_clock::now()); 4020b57cec5SDimitry Andric} 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 4050b57cec5SDimitry Andricvoid yield() _NOEXCEPT {__libcpp_thread_yield();} 4060b57cec5SDimitry Andric 4070eae32dcSDimitry Andric} // namespace this_thread 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric#endif // !_LIBCPP_HAS_NO_THREADS 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric_LIBCPP_POP_MACROS 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric#endif // _LIBCPP_THREAD 416