thread revision 261272
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> 102227825Stheraven 103227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 104227825Stheraven#pragma GCC system_header 105227825Stheraven#endif 106227825Stheraven 107227825Stheraven#define __STDCPP_THREADS__ __cplusplus 108227825Stheraven 109227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 110227825Stheraven 111227825Stheraventemplate <class _Tp> 112227825Stheravenclass __thread_specific_ptr 113227825Stheraven{ 114227825Stheraven pthread_key_t __key_; 115227825Stheraven 116227825Stheraven __thread_specific_ptr(const __thread_specific_ptr&); 117227825Stheraven __thread_specific_ptr& operator=(const __thread_specific_ptr&); 118227825Stheraven 119227825Stheraven static void __at_thread_exit(void*); 120227825Stheravenpublic: 121227825Stheraven typedef _Tp* pointer; 122227825Stheraven 123227825Stheraven __thread_specific_ptr(); 124227825Stheraven ~__thread_specific_ptr(); 125227825Stheraven 126227825Stheraven _LIBCPP_INLINE_VISIBILITY 127227825Stheraven pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} 128227825Stheraven _LIBCPP_INLINE_VISIBILITY 129227825Stheraven pointer operator*() const {return *get();} 130227825Stheraven _LIBCPP_INLINE_VISIBILITY 131227825Stheraven pointer operator->() const {return get();} 132227825Stheraven pointer release(); 133227825Stheraven void reset(pointer __p = nullptr); 134227825Stheraven}; 135227825Stheraven 136227825Stheraventemplate <class _Tp> 137227825Stheravenvoid 138227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 139227825Stheraven{ 140227825Stheraven delete static_cast<pointer>(__p); 141227825Stheraven} 142227825Stheraven 143227825Stheraventemplate <class _Tp> 144227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr() 145227825Stheraven{ 146227825Stheraven int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 147249989Sdim#ifndef _LIBCPP_NO_EXCEPTIONS 148227825Stheraven if (__ec) 149227825Stheraven throw system_error(error_code(__ec, system_category()), 150227825Stheraven "__thread_specific_ptr construction failed"); 151249989Sdim#endif 152227825Stheraven} 153227825Stheraven 154227825Stheraventemplate <class _Tp> 155227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 156227825Stheraven{ 157227825Stheraven pthread_key_delete(__key_); 158227825Stheraven} 159227825Stheraven 160227825Stheraventemplate <class _Tp> 161227825Stheraventypename __thread_specific_ptr<_Tp>::pointer 162227825Stheraven__thread_specific_ptr<_Tp>::release() 163227825Stheraven{ 164227825Stheraven pointer __p = get(); 165227825Stheraven pthread_setspecific(__key_, 0); 166227825Stheraven return __p; 167227825Stheraven} 168227825Stheraven 169227825Stheraventemplate <class _Tp> 170227825Stheravenvoid 171227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p) 172227825Stheraven{ 173227825Stheraven pointer __p_old = get(); 174227825Stheraven pthread_setspecific(__key_, __p); 175227825Stheraven delete __p_old; 176227825Stheraven} 177227825Stheraven 178249989Sdimclass _LIBCPP_TYPE_VIS thread; 179249989Sdimclass _LIBCPP_TYPE_VIS __thread_id; 180227825Stheraven 181227825Stheravennamespace this_thread 182227825Stheraven{ 183227825Stheraven 184241900Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 185227825Stheraven 186227825Stheraven} // this_thread 187227825Stheraven 188261272Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 189232924Stheraven 190261272Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id 191227825Stheraven{ 192227825Stheraven // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 193227825Stheraven // NULL is the no-thread value on Darwin. Someone needs to check 194227825Stheraven // on other platforms. We assume 0 works everywhere for now. 195227825Stheraven pthread_t __id_; 196227825Stheraven 197227825Stheravenpublic: 198227825Stheraven _LIBCPP_INLINE_VISIBILITY 199241900Sdim __thread_id() _NOEXCEPT : __id_(0) {} 200227825Stheraven 201227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 202241900Sdim bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 203227825Stheraven {return __x.__id_ == __y.__id_;} 204227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 205241900Sdim bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 206227825Stheraven {return !(__x == __y);} 207227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 208241900Sdim bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 209227825Stheraven {return __x.__id_ < __y.__id_;} 210227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 211241900Sdim bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 212227825Stheraven {return !(__y < __x);} 213227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 214241900Sdim bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 215227825Stheraven {return __y < __x ;} 216227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 217241900Sdim bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 218227825Stheraven {return !(__x < __y);} 219227825Stheraven 220227825Stheraven template<class _CharT, class _Traits> 221227825Stheraven friend 222227825Stheraven _LIBCPP_INLINE_VISIBILITY 223227825Stheraven basic_ostream<_CharT, _Traits>& 224227825Stheraven operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 225227825Stheraven {return __os << __id.__id_;} 226227825Stheraven 227227825Stheravenprivate: 228227825Stheraven _LIBCPP_INLINE_VISIBILITY 229227825Stheraven __thread_id(pthread_t __id) : __id_(__id) {} 230227825Stheraven 231241900Sdim friend __thread_id this_thread::get_id() _NOEXCEPT; 232249989Sdim friend class _LIBCPP_TYPE_VIS thread; 233261272Sdim friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 234227825Stheraven}; 235227825Stheraven 236227825Stheraventemplate<> 237261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> 238227825Stheraven : public unary_function<__thread_id, size_t> 239227825Stheraven{ 240227825Stheraven _LIBCPP_INLINE_VISIBILITY 241227825Stheraven size_t operator()(__thread_id __v) const 242227825Stheraven { 243232924Stheraven return hash<pthread_t>()(__v.__id_); 244227825Stheraven } 245227825Stheraven}; 246227825Stheraven 247227825Stheravennamespace this_thread 248227825Stheraven{ 249227825Stheraven 250227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 251227825Stheraven__thread_id 252241900Sdimget_id() _NOEXCEPT 253227825Stheraven{ 254227825Stheraven return pthread_self(); 255227825Stheraven} 256227825Stheraven 257227825Stheraven} // this_thread 258227825Stheraven 259249989Sdimclass _LIBCPP_TYPE_VIS thread 260227825Stheraven{ 261227825Stheraven pthread_t __t_; 262227825Stheraven 263227825Stheraven thread(const thread&); 264227825Stheraven thread& operator=(const thread&); 265227825Stheravenpublic: 266227825Stheraven typedef __thread_id id; 267227825Stheraven typedef pthread_t native_handle_type; 268227825Stheraven 269227825Stheraven _LIBCPP_INLINE_VISIBILITY 270241900Sdim thread() _NOEXCEPT : __t_(0) {} 271227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 272232924Stheraven template <class _Fp, class ..._Args, 273227825Stheraven class = typename enable_if 274227825Stheraven < 275232924Stheraven !is_same<typename decay<_Fp>::type, thread>::value 276227825Stheraven >::type 277227825Stheraven > 278232924Stheraven explicit thread(_Fp&& __f, _Args&&... __args); 279227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 280232924Stheraven template <class _Fp> explicit thread(_Fp __f); 281227825Stheraven#endif 282227825Stheraven ~thread(); 283227825Stheraven 284227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 285227825Stheraven _LIBCPP_INLINE_VISIBILITY 286241900Sdim thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 287241900Sdim thread& operator=(thread&& __t) _NOEXCEPT; 288227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 289227825Stheraven 290227825Stheraven _LIBCPP_INLINE_VISIBILITY 291241900Sdim void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 292227825Stheraven 293227825Stheraven _LIBCPP_INLINE_VISIBILITY 294241900Sdim bool joinable() const _NOEXCEPT {return __t_ != 0;} 295227825Stheraven void join(); 296227825Stheraven void detach(); 297227825Stheraven _LIBCPP_INLINE_VISIBILITY 298241900Sdim id get_id() const _NOEXCEPT {return __t_;} 299227825Stheraven _LIBCPP_INLINE_VISIBILITY 300241900Sdim native_handle_type native_handle() _NOEXCEPT {return __t_;} 301227825Stheraven 302241900Sdim static unsigned hardware_concurrency() _NOEXCEPT; 303227825Stheraven}; 304227825Stheraven 305227825Stheravenclass __assoc_sub_state; 306227825Stheraven 307227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp; 308227825Stheraven 309261272Sdimclass _LIBCPP_TYPE_VIS __thread_struct 310227825Stheraven{ 311227825Stheraven __thread_struct_imp* __p_; 312227825Stheraven 313227825Stheraven __thread_struct(const __thread_struct&); 314227825Stheraven __thread_struct& operator=(const __thread_struct&); 315227825Stheravenpublic: 316227825Stheraven __thread_struct(); 317227825Stheraven ~__thread_struct(); 318227825Stheraven 319227825Stheraven void notify_all_at_thread_exit(condition_variable*, mutex*); 320227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state*); 321227825Stheraven}; 322227825Stheraven 323261272Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 324227825Stheraven 325227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 326227825Stheraven 327232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices> 328227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 329227825Stheravenvoid 330249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) 331227825Stheraven{ 332227825Stheraven __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 333227825Stheraven} 334227825Stheraven 335232924Stheraventemplate <class _Fp> 336227825Stheravenvoid* 337227825Stheraven__thread_proxy(void* __vp) 338227825Stheraven{ 339227825Stheraven __thread_local_data().reset(new __thread_struct); 340232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 341232924Stheraven typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 342249989Sdim __thread_execute(*__p, _Index()); 343227825Stheraven return nullptr; 344227825Stheraven} 345227825Stheraven 346232924Stheraventemplate <class _Fp, class ..._Args, 347227825Stheraven class 348227825Stheraven > 349232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args) 350227825Stheraven{ 351232924Stheraven typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 352232924Stheraven _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), 353227825Stheraven __decay_copy(_VSTD::forward<_Args>(__args))...)); 354232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 355227825Stheraven if (__ec == 0) 356227825Stheraven __p.release(); 357227825Stheraven else 358227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 359227825Stheraven} 360227825Stheraven 361227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 362227825Stheraven 363232924Stheraventemplate <class _Fp> 364227825Stheravenvoid* 365227825Stheraven__thread_proxy(void* __vp) 366227825Stheraven{ 367227825Stheraven __thread_local_data().reset(new __thread_struct); 368232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 369227825Stheraven (*__p)(); 370227825Stheraven return nullptr; 371227825Stheraven} 372227825Stheraven 373232924Stheraventemplate <class _Fp> 374232924Stheraventhread::thread(_Fp __f) 375227825Stheraven{ 376232924Stheraven std::unique_ptr<_Fp> __p(new _Fp(__f)); 377232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); 378227825Stheraven if (__ec == 0) 379227825Stheraven __p.release(); 380227825Stheraven else 381227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 382227825Stheraven} 383227825Stheraven 384227825Stheraven#endif // _LIBCPP_HAS_NO_VARIADICS 385227825Stheraven 386227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 387227825Stheraven 388227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 389227825Stheraventhread& 390241900Sdimthread::operator=(thread&& __t) _NOEXCEPT 391227825Stheraven{ 392227825Stheraven if (__t_ != 0) 393227825Stheraven terminate(); 394227825Stheraven __t_ = __t.__t_; 395227825Stheraven __t.__t_ = 0; 396227825Stheraven return *this; 397227825Stheraven} 398227825Stheraven 399227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 400227825Stheraven 401227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 402241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 403227825Stheraven 404227825Stheravennamespace this_thread 405227825Stheraven{ 406227825Stheraven 407261272Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns); 408227825Stheraven 409227825Stheraventemplate <class _Rep, class _Period> 410227825Stheravenvoid 411227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d) 412227825Stheraven{ 413227825Stheraven using namespace chrono; 414241900Sdim if (__d > duration<_Rep, _Period>::zero()) 415241900Sdim { 416241900Sdim _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 417241900Sdim nanoseconds __ns; 418241900Sdim if (__d < _Max) 419241900Sdim { 420241900Sdim __ns = duration_cast<nanoseconds>(__d); 421241900Sdim if (__ns < __d) 422241900Sdim ++__ns; 423241900Sdim } 424241900Sdim else 425241900Sdim __ns = nanoseconds::max(); 426241900Sdim sleep_for(__ns); 427241900Sdim } 428227825Stheraven} 429227825Stheraven 430227825Stheraventemplate <class _Clock, class _Duration> 431227825Stheravenvoid 432227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t) 433227825Stheraven{ 434227825Stheraven using namespace chrono; 435227825Stheraven mutex __mut; 436227825Stheraven condition_variable __cv; 437227825Stheraven unique_lock<mutex> __lk(__mut); 438227825Stheraven while (_Clock::now() < __t) 439227825Stheraven __cv.wait_until(__lk, __t); 440227825Stheraven} 441227825Stheraven 442227825Stheraventemplate <class _Duration> 443227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 444227825Stheravenvoid 445227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 446227825Stheraven{ 447227825Stheraven using namespace chrono; 448227825Stheraven sleep_for(__t - steady_clock::now()); 449227825Stheraven} 450227825Stheraven 451227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 452241900Sdimvoid yield() _NOEXCEPT {sched_yield();} 453227825Stheraven 454227825Stheraven} // this_thread 455227825Stheraven 456227825Stheraven_LIBCPP_END_NAMESPACE_STD 457227825Stheraven 458227825Stheraven#endif // _LIBCPP_THREAD 459