1227825Stheraven// -*- C++ -*- 2227825Stheraven//===--------------------------- thread -----------------------------------===// 3227825Stheraven// 4227825Stheraven// The LLVM Compiler Infrastructure 5227825Stheraven// 6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 7227825Stheraven// Source Licenses. See LICENSE.TXT for details. 8227825Stheraven// 9227825Stheraven//===----------------------------------------------------------------------===// 10227825Stheraven 11227825Stheraven#ifndef _LIBCPP_THREAD 12227825Stheraven#define _LIBCPP_THREAD 13227825Stheraven 14227825Stheraven/* 15227825Stheraven 16227825Stheraven thread synopsis 17227825Stheraven 18227825Stheraven#define __STDCPP_THREADS__ __cplusplus 19227825Stheraven 20227825Stheravennamespace std 21227825Stheraven{ 22227825Stheraven 23227825Stheravenclass thread 24227825Stheraven{ 25227825Stheravenpublic: 26227825Stheraven class id; 27227825Stheraven typedef pthread_t native_handle_type; 28227825Stheraven 29241900Sdim thread() noexcept; 30227825Stheraven template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 31227825Stheraven ~thread(); 32227825Stheraven 33227825Stheraven thread(const thread&) = delete; 34241900Sdim thread(thread&& t) noexcept; 35227825Stheraven 36227825Stheraven thread& operator=(const thread&) = delete; 37241900Sdim thread& operator=(thread&& t) noexcept; 38227825Stheraven 39241900Sdim void swap(thread& t) noexcept; 40227825Stheraven 41241900Sdim bool joinable() const noexcept; 42227825Stheraven void join(); 43227825Stheraven void detach(); 44241900Sdim id get_id() const noexcept; 45227825Stheraven native_handle_type native_handle(); 46227825Stheraven 47241900Sdim static unsigned hardware_concurrency() noexcept; 48227825Stheraven}; 49227825Stheraven 50241900Sdimvoid swap(thread& x, thread& y) noexcept; 51227825Stheraven 52227825Stheravenclass thread::id 53227825Stheraven{ 54227825Stheravenpublic: 55241900Sdim id() noexcept; 56227825Stheraven}; 57227825Stheraven 58241900Sdimbool operator==(thread::id x, thread::id y) noexcept; 59241900Sdimbool operator!=(thread::id x, thread::id y) noexcept; 60241900Sdimbool operator< (thread::id x, thread::id y) noexcept; 61241900Sdimbool operator<=(thread::id x, thread::id y) noexcept; 62241900Sdimbool operator> (thread::id x, thread::id y) noexcept; 63241900Sdimbool operator>=(thread::id x, thread::id y) noexcept; 64227825Stheraven 65227825Stheraventemplate<class charT, class traits> 66227825Stheravenbasic_ostream<charT, traits>& 67227825Stheravenoperator<<(basic_ostream<charT, traits>& out, thread::id id); 68227825Stheraven 69227825Stheravennamespace this_thread 70227825Stheraven{ 71227825Stheraven 72241900Sdimthread::id get_id() noexcept; 73227825Stheraven 74241900Sdimvoid yield() noexcept; 75227825Stheraven 76227825Stheraventemplate <class Clock, class Duration> 77227825Stheravenvoid sleep_until(const chrono::time_point<Clock, Duration>& abs_time); 78227825Stheraven 79227825Stheraventemplate <class Rep, class Period> 80227825Stheravenvoid sleep_for(const chrono::duration<Rep, Period>& rel_time); 81227825Stheraven 82227825Stheraven} // this_thread 83227825Stheraven 84227825Stheraven} // std 85227825Stheraven 86227825Stheraven*/ 87227825Stheraven 88227825Stheraven#include <__config> 89227825Stheraven#include <iosfwd> 90227825Stheraven#include <__functional_base> 91227825Stheraven#include <type_traits> 92227825Stheraven#include <cstddef> 93227825Stheraven#include <functional> 94227825Stheraven#include <memory> 95227825Stheraven#include <system_error> 96227825Stheraven#include <chrono> 97227825Stheraven#include <__mutex_base> 98227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 99227825Stheraven#include <tuple> 100227825Stheraven#endif 101227825Stheraven#include <pthread.h> 102276792Sdim#include <sched.h> 103227825Stheraven 104227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 105227825Stheraven#pragma GCC system_header 106227825Stheraven#endif 107227825Stheraven 108227825Stheraven#define __STDCPP_THREADS__ __cplusplus 109227825Stheraven 110276792Sdim#ifdef _LIBCPP_HAS_NO_THREADS 111276792Sdim#error <thread> is not supported on this single threaded system 112276792Sdim#else // !_LIBCPP_HAS_NO_THREADS 113276792Sdim 114227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 115227825Stheraven 116300770Sdimtemplate <class _Tp> class __thread_specific_ptr; 117300770Sdimclass _LIBCPP_TYPE_VIS __thread_struct; 118300770Sdimclass _LIBCPP_HIDDEN __thread_struct_imp; 119300770Sdimclass __assoc_sub_state; 120300770Sdim 121300770Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 122300770Sdim 123300770Sdimclass _LIBCPP_TYPE_VIS __thread_struct 124300770Sdim{ 125300770Sdim __thread_struct_imp* __p_; 126300770Sdim 127300770Sdim __thread_struct(const __thread_struct&); 128300770Sdim __thread_struct& operator=(const __thread_struct&); 129300770Sdimpublic: 130300770Sdim __thread_struct(); 131300770Sdim ~__thread_struct(); 132300770Sdim 133300770Sdim void notify_all_at_thread_exit(condition_variable*, mutex*); 134300770Sdim void __make_ready_at_thread_exit(__assoc_sub_state*); 135300770Sdim}; 136300770Sdim 137227825Stheraventemplate <class _Tp> 138227825Stheravenclass __thread_specific_ptr 139227825Stheraven{ 140227825Stheraven pthread_key_t __key_; 141227825Stheraven 142300770Sdim // Only __thread_local_data() may construct a __thread_specific_ptr 143300770Sdim // and only with _Tp == __thread_struct. 144300770Sdim static_assert((is_same<_Tp, __thread_struct>::value), ""); 145300770Sdim __thread_specific_ptr(); 146300770Sdim friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 147300770Sdim 148227825Stheraven __thread_specific_ptr(const __thread_specific_ptr&); 149227825Stheraven __thread_specific_ptr& operator=(const __thread_specific_ptr&); 150227825Stheraven 151227825Stheraven static void __at_thread_exit(void*); 152227825Stheravenpublic: 153227825Stheraven typedef _Tp* pointer; 154227825Stheraven 155227825Stheraven ~__thread_specific_ptr(); 156227825Stheraven 157227825Stheraven _LIBCPP_INLINE_VISIBILITY 158227825Stheraven pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} 159227825Stheraven _LIBCPP_INLINE_VISIBILITY 160227825Stheraven pointer operator*() const {return *get();} 161227825Stheraven _LIBCPP_INLINE_VISIBILITY 162227825Stheraven pointer operator->() const {return get();} 163227825Stheraven pointer release(); 164227825Stheraven void reset(pointer __p = nullptr); 165227825Stheraven}; 166227825Stheraven 167227825Stheraventemplate <class _Tp> 168227825Stheravenvoid 169227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 170227825Stheraven{ 171227825Stheraven delete static_cast<pointer>(__p); 172227825Stheraven} 173227825Stheraven 174227825Stheraventemplate <class _Tp> 175227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr() 176227825Stheraven{ 177227825Stheraven int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 178249989Sdim#ifndef _LIBCPP_NO_EXCEPTIONS 179227825Stheraven if (__ec) 180227825Stheraven throw system_error(error_code(__ec, system_category()), 181227825Stheraven "__thread_specific_ptr construction failed"); 182249989Sdim#endif 183227825Stheraven} 184227825Stheraven 185227825Stheraventemplate <class _Tp> 186227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 187227825Stheraven{ 188300770Sdim // __thread_specific_ptr is only created with a static storage duration 189300770Sdim // so this destructor is only invoked during program termination. Invoking 190300770Sdim // pthread_key_delete(__key_) may prevent other threads from deleting their 191300770Sdim // thread local data. For this reason we leak the key. 192227825Stheraven} 193227825Stheraven 194227825Stheraventemplate <class _Tp> 195227825Stheraventypename __thread_specific_ptr<_Tp>::pointer 196227825Stheraven__thread_specific_ptr<_Tp>::release() 197227825Stheraven{ 198227825Stheraven pointer __p = get(); 199227825Stheraven pthread_setspecific(__key_, 0); 200227825Stheraven return __p; 201227825Stheraven} 202227825Stheraven 203227825Stheraventemplate <class _Tp> 204227825Stheravenvoid 205227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p) 206227825Stheraven{ 207227825Stheraven pointer __p_old = get(); 208227825Stheraven pthread_setspecific(__key_, __p); 209227825Stheraven delete __p_old; 210227825Stheraven} 211227825Stheraven 212249989Sdimclass _LIBCPP_TYPE_VIS thread; 213249989Sdimclass _LIBCPP_TYPE_VIS __thread_id; 214227825Stheraven 215227825Stheravennamespace this_thread 216227825Stheraven{ 217227825Stheraven 218241900Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 219227825Stheraven 220227825Stheraven} // this_thread 221227825Stheraven 222261272Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 223232924Stheraven 224261272Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id 225227825Stheraven{ 226227825Stheraven // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 227227825Stheraven // NULL is the no-thread value on Darwin. Someone needs to check 228227825Stheraven // on other platforms. We assume 0 works everywhere for now. 229227825Stheraven pthread_t __id_; 230227825Stheraven 231227825Stheravenpublic: 232227825Stheraven _LIBCPP_INLINE_VISIBILITY 233241900Sdim __thread_id() _NOEXCEPT : __id_(0) {} 234227825Stheraven 235227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 236241900Sdim bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 237227825Stheraven {return __x.__id_ == __y.__id_;} 238227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 239241900Sdim bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 240227825Stheraven {return !(__x == __y);} 241227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 242241900Sdim bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 243227825Stheraven {return __x.__id_ < __y.__id_;} 244227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 245241900Sdim bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 246227825Stheraven {return !(__y < __x);} 247227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 248241900Sdim bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 249227825Stheraven {return __y < __x ;} 250227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 251241900Sdim bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 252227825Stheraven {return !(__x < __y);} 253227825Stheraven 254227825Stheraven template<class _CharT, class _Traits> 255227825Stheraven friend 256227825Stheraven _LIBCPP_INLINE_VISIBILITY 257227825Stheraven basic_ostream<_CharT, _Traits>& 258227825Stheraven operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 259227825Stheraven {return __os << __id.__id_;} 260227825Stheraven 261227825Stheravenprivate: 262227825Stheraven _LIBCPP_INLINE_VISIBILITY 263227825Stheraven __thread_id(pthread_t __id) : __id_(__id) {} 264227825Stheraven 265241900Sdim friend __thread_id this_thread::get_id() _NOEXCEPT; 266249989Sdim friend class _LIBCPP_TYPE_VIS thread; 267261272Sdim friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 268227825Stheraven}; 269227825Stheraven 270227825Stheraventemplate<> 271261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> 272227825Stheraven : public unary_function<__thread_id, size_t> 273227825Stheraven{ 274227825Stheraven _LIBCPP_INLINE_VISIBILITY 275227825Stheraven size_t operator()(__thread_id __v) const 276227825Stheraven { 277232924Stheraven return hash<pthread_t>()(__v.__id_); 278227825Stheraven } 279227825Stheraven}; 280227825Stheraven 281227825Stheravennamespace this_thread 282227825Stheraven{ 283227825Stheraven 284227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 285227825Stheraven__thread_id 286241900Sdimget_id() _NOEXCEPT 287227825Stheraven{ 288227825Stheraven return pthread_self(); 289227825Stheraven} 290227825Stheraven 291227825Stheraven} // this_thread 292227825Stheraven 293249989Sdimclass _LIBCPP_TYPE_VIS thread 294227825Stheraven{ 295227825Stheraven pthread_t __t_; 296227825Stheraven 297227825Stheraven thread(const thread&); 298227825Stheraven thread& operator=(const thread&); 299227825Stheravenpublic: 300227825Stheraven typedef __thread_id id; 301227825Stheraven typedef pthread_t native_handle_type; 302227825Stheraven 303227825Stheraven _LIBCPP_INLINE_VISIBILITY 304241900Sdim thread() _NOEXCEPT : __t_(0) {} 305227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 306232924Stheraven template <class _Fp, class ..._Args, 307227825Stheraven class = typename enable_if 308227825Stheraven < 309232924Stheraven !is_same<typename decay<_Fp>::type, thread>::value 310227825Stheraven >::type 311227825Stheraven > 312232924Stheraven explicit thread(_Fp&& __f, _Args&&... __args); 313227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 314232924Stheraven template <class _Fp> explicit thread(_Fp __f); 315227825Stheraven#endif 316227825Stheraven ~thread(); 317227825Stheraven 318227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 319227825Stheraven _LIBCPP_INLINE_VISIBILITY 320241900Sdim thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 321300770Sdim _LIBCPP_INLINE_VISIBILITY 322241900Sdim thread& operator=(thread&& __t) _NOEXCEPT; 323227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 324227825Stheraven 325227825Stheraven _LIBCPP_INLINE_VISIBILITY 326241900Sdim void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 327227825Stheraven 328227825Stheraven _LIBCPP_INLINE_VISIBILITY 329241900Sdim bool joinable() const _NOEXCEPT {return __t_ != 0;} 330227825Stheraven void join(); 331227825Stheraven void detach(); 332227825Stheraven _LIBCPP_INLINE_VISIBILITY 333241900Sdim id get_id() const _NOEXCEPT {return __t_;} 334227825Stheraven _LIBCPP_INLINE_VISIBILITY 335241900Sdim native_handle_type native_handle() _NOEXCEPT {return __t_;} 336227825Stheraven 337241900Sdim static unsigned hardware_concurrency() _NOEXCEPT; 338227825Stheraven}; 339227825Stheraven 340227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 341227825Stheraven 342232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices> 343227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 344227825Stheravenvoid 345249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) 346227825Stheraven{ 347227825Stheraven __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 348227825Stheraven} 349227825Stheraven 350232924Stheraventemplate <class _Fp> 351227825Stheravenvoid* 352227825Stheraven__thread_proxy(void* __vp) 353227825Stheraven{ 354227825Stheraven __thread_local_data().reset(new __thread_struct); 355232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 356232924Stheraven typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 357249989Sdim __thread_execute(*__p, _Index()); 358227825Stheraven return nullptr; 359227825Stheraven} 360227825Stheraven 361232924Stheraventemplate <class _Fp, class ..._Args, 362227825Stheraven class 363227825Stheraven > 364232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args) 365227825Stheraven{ 366232924Stheraven typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 367232924Stheraven _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), 368227825Stheraven __decay_copy(_VSTD::forward<_Args>(__args))...)); 369232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 370227825Stheraven if (__ec == 0) 371227825Stheraven __p.release(); 372227825Stheraven else 373227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 374227825Stheraven} 375227825Stheraven 376227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 377227825Stheraven 378232924Stheraventemplate <class _Fp> 379227825Stheravenvoid* 380227825Stheraven__thread_proxy(void* __vp) 381227825Stheraven{ 382227825Stheraven __thread_local_data().reset(new __thread_struct); 383232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 384227825Stheraven (*__p)(); 385227825Stheraven return nullptr; 386227825Stheraven} 387227825Stheraven 388232924Stheraventemplate <class _Fp> 389232924Stheraventhread::thread(_Fp __f) 390227825Stheraven{ 391232924Stheraven std::unique_ptr<_Fp> __p(new _Fp(__f)); 392232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); 393227825Stheraven if (__ec == 0) 394227825Stheraven __p.release(); 395227825Stheraven else 396227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 397227825Stheraven} 398227825Stheraven 399227825Stheraven#endif // _LIBCPP_HAS_NO_VARIADICS 400227825Stheraven 401227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 402227825Stheraven 403300770Sdiminline 404227825Stheraventhread& 405241900Sdimthread::operator=(thread&& __t) _NOEXCEPT 406227825Stheraven{ 407227825Stheraven if (__t_ != 0) 408227825Stheraven terminate(); 409227825Stheraven __t_ = __t.__t_; 410227825Stheraven __t.__t_ = 0; 411227825Stheraven return *this; 412227825Stheraven} 413227825Stheraven 414227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 415227825Stheraven 416227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 417241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 418227825Stheraven 419227825Stheravennamespace this_thread 420227825Stheraven{ 421227825Stheraven 422261272Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns); 423227825Stheraven 424227825Stheraventemplate <class _Rep, class _Period> 425227825Stheravenvoid 426227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d) 427227825Stheraven{ 428227825Stheraven using namespace chrono; 429241900Sdim if (__d > duration<_Rep, _Period>::zero()) 430241900Sdim { 431241900Sdim _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 432241900Sdim nanoseconds __ns; 433241900Sdim if (__d < _Max) 434241900Sdim { 435241900Sdim __ns = duration_cast<nanoseconds>(__d); 436241900Sdim if (__ns < __d) 437241900Sdim ++__ns; 438241900Sdim } 439241900Sdim else 440241900Sdim __ns = nanoseconds::max(); 441241900Sdim sleep_for(__ns); 442241900Sdim } 443227825Stheraven} 444227825Stheraven 445227825Stheraventemplate <class _Clock, class _Duration> 446227825Stheravenvoid 447227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t) 448227825Stheraven{ 449227825Stheraven using namespace chrono; 450227825Stheraven mutex __mut; 451227825Stheraven condition_variable __cv; 452227825Stheraven unique_lock<mutex> __lk(__mut); 453227825Stheraven while (_Clock::now() < __t) 454227825Stheraven __cv.wait_until(__lk, __t); 455227825Stheraven} 456227825Stheraven 457227825Stheraventemplate <class _Duration> 458227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 459227825Stheravenvoid 460227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 461227825Stheraven{ 462227825Stheraven using namespace chrono; 463227825Stheraven sleep_for(__t - steady_clock::now()); 464227825Stheraven} 465227825Stheraven 466227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 467241900Sdimvoid yield() _NOEXCEPT {sched_yield();} 468227825Stheraven 469227825Stheraven} // this_thread 470227825Stheraven 471227825Stheraven_LIBCPP_END_NAMESPACE_STD 472227825Stheraven 473276792Sdim#endif // !_LIBCPP_HAS_NO_THREADS 474276792Sdim 475227825Stheraven#endif // _LIBCPP_THREAD 476