thread revision 249989
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 188249989Sdimclass _LIBCPP_TYPE_VIS __thread_id; 189249989Sdimtemplate<> struct _LIBCPP_TYPE_VIS hash<__thread_id>; 190232924Stheraven 191249989Sdimclass _LIBCPP_TYPE_VIS __thread_id 192227825Stheraven{ 193227825Stheraven // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 194227825Stheraven // NULL is the no-thread value on Darwin. Someone needs to check 195227825Stheraven // on other platforms. We assume 0 works everywhere for now. 196227825Stheraven pthread_t __id_; 197227825Stheraven 198227825Stheravenpublic: 199227825Stheraven _LIBCPP_INLINE_VISIBILITY 200241900Sdim __thread_id() _NOEXCEPT : __id_(0) {} 201227825Stheraven 202227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 203241900Sdim bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 204227825Stheraven {return __x.__id_ == __y.__id_;} 205227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 206241900Sdim bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 207227825Stheraven {return !(__x == __y);} 208227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 209241900Sdim bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 210227825Stheraven {return __x.__id_ < __y.__id_;} 211227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 212241900Sdim bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 213227825Stheraven {return !(__y < __x);} 214227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 215241900Sdim bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 216227825Stheraven {return __y < __x ;} 217227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 218241900Sdim bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 219227825Stheraven {return !(__x < __y);} 220227825Stheraven 221227825Stheraven template<class _CharT, class _Traits> 222227825Stheraven friend 223227825Stheraven _LIBCPP_INLINE_VISIBILITY 224227825Stheraven basic_ostream<_CharT, _Traits>& 225227825Stheraven operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 226227825Stheraven {return __os << __id.__id_;} 227227825Stheraven 228227825Stheravenprivate: 229227825Stheraven _LIBCPP_INLINE_VISIBILITY 230227825Stheraven __thread_id(pthread_t __id) : __id_(__id) {} 231227825Stheraven 232241900Sdim friend __thread_id this_thread::get_id() _NOEXCEPT; 233249989Sdim friend class _LIBCPP_TYPE_VIS thread; 234249989Sdim friend struct _LIBCPP_TYPE_VIS hash<__thread_id>; 235227825Stheraven}; 236227825Stheraven 237227825Stheraventemplate<> 238249989Sdimstruct _LIBCPP_TYPE_VIS hash<__thread_id> 239227825Stheraven : public unary_function<__thread_id, size_t> 240227825Stheraven{ 241227825Stheraven _LIBCPP_INLINE_VISIBILITY 242227825Stheraven size_t operator()(__thread_id __v) const 243227825Stheraven { 244232924Stheraven return hash<pthread_t>()(__v.__id_); 245227825Stheraven } 246227825Stheraven}; 247227825Stheraven 248227825Stheravennamespace this_thread 249227825Stheraven{ 250227825Stheraven 251227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 252227825Stheraven__thread_id 253241900Sdimget_id() _NOEXCEPT 254227825Stheraven{ 255227825Stheraven return pthread_self(); 256227825Stheraven} 257227825Stheraven 258227825Stheraven} // this_thread 259227825Stheraven 260249989Sdimclass _LIBCPP_TYPE_VIS thread 261227825Stheraven{ 262227825Stheraven pthread_t __t_; 263227825Stheraven 264227825Stheraven thread(const thread&); 265227825Stheraven thread& operator=(const thread&); 266227825Stheravenpublic: 267227825Stheraven typedef __thread_id id; 268227825Stheraven typedef pthread_t native_handle_type; 269227825Stheraven 270227825Stheraven _LIBCPP_INLINE_VISIBILITY 271241900Sdim thread() _NOEXCEPT : __t_(0) {} 272227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 273232924Stheraven template <class _Fp, class ..._Args, 274227825Stheraven class = typename enable_if 275227825Stheraven < 276232924Stheraven !is_same<typename decay<_Fp>::type, thread>::value 277227825Stheraven >::type 278227825Stheraven > 279232924Stheraven explicit thread(_Fp&& __f, _Args&&... __args); 280227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 281232924Stheraven template <class _Fp> explicit thread(_Fp __f); 282227825Stheraven#endif 283227825Stheraven ~thread(); 284227825Stheraven 285227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 286227825Stheraven _LIBCPP_INLINE_VISIBILITY 287241900Sdim thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 288241900Sdim thread& operator=(thread&& __t) _NOEXCEPT; 289227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 290227825Stheraven 291227825Stheraven _LIBCPP_INLINE_VISIBILITY 292241900Sdim void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 293227825Stheraven 294227825Stheraven _LIBCPP_INLINE_VISIBILITY 295241900Sdim bool joinable() const _NOEXCEPT {return __t_ != 0;} 296227825Stheraven void join(); 297227825Stheraven void detach(); 298227825Stheraven _LIBCPP_INLINE_VISIBILITY 299241900Sdim id get_id() const _NOEXCEPT {return __t_;} 300227825Stheraven _LIBCPP_INLINE_VISIBILITY 301241900Sdim native_handle_type native_handle() _NOEXCEPT {return __t_;} 302227825Stheraven 303241900Sdim static unsigned hardware_concurrency() _NOEXCEPT; 304227825Stheraven}; 305227825Stheraven 306227825Stheravenclass __assoc_sub_state; 307227825Stheraven 308227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp; 309227825Stheraven 310227825Stheravenclass __thread_struct 311227825Stheraven{ 312227825Stheraven __thread_struct_imp* __p_; 313227825Stheraven 314227825Stheraven __thread_struct(const __thread_struct&); 315227825Stheraven __thread_struct& operator=(const __thread_struct&); 316227825Stheravenpublic: 317227825Stheraven __thread_struct(); 318227825Stheraven ~__thread_struct(); 319227825Stheraven 320227825Stheraven void notify_all_at_thread_exit(condition_variable*, mutex*); 321227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state*); 322227825Stheraven}; 323227825Stheraven 324227825Stheraven__thread_specific_ptr<__thread_struct>& __thread_local_data(); 325227825Stheraven 326227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 327227825Stheraven 328232924Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices> 329227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 330227825Stheravenvoid 331249989Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) 332227825Stheraven{ 333227825Stheraven __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 334227825Stheraven} 335227825Stheraven 336232924Stheraventemplate <class _Fp> 337227825Stheravenvoid* 338227825Stheraven__thread_proxy(void* __vp) 339227825Stheraven{ 340227825Stheraven __thread_local_data().reset(new __thread_struct); 341232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 342232924Stheraven typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 343249989Sdim __thread_execute(*__p, _Index()); 344227825Stheraven return nullptr; 345227825Stheraven} 346227825Stheraven 347232924Stheraventemplate <class _Fp, class ..._Args, 348227825Stheraven class 349227825Stheraven > 350232924Stheraventhread::thread(_Fp&& __f, _Args&&... __args) 351227825Stheraven{ 352232924Stheraven typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 353232924Stheraven _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), 354227825Stheraven __decay_copy(_VSTD::forward<_Args>(__args))...)); 355232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 356227825Stheraven if (__ec == 0) 357227825Stheraven __p.release(); 358227825Stheraven else 359227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 360227825Stheraven} 361227825Stheraven 362227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 363227825Stheraven 364232924Stheraventemplate <class _Fp> 365227825Stheravenvoid* 366227825Stheraven__thread_proxy(void* __vp) 367227825Stheraven{ 368227825Stheraven __thread_local_data().reset(new __thread_struct); 369232924Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 370227825Stheraven (*__p)(); 371227825Stheraven return nullptr; 372227825Stheraven} 373227825Stheraven 374232924Stheraventemplate <class _Fp> 375232924Stheraventhread::thread(_Fp __f) 376227825Stheraven{ 377232924Stheraven std::unique_ptr<_Fp> __p(new _Fp(__f)); 378232924Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); 379227825Stheraven if (__ec == 0) 380227825Stheraven __p.release(); 381227825Stheraven else 382227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 383227825Stheraven} 384227825Stheraven 385227825Stheraven#endif // _LIBCPP_HAS_NO_VARIADICS 386227825Stheraven 387227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 388227825Stheraven 389227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 390227825Stheraventhread& 391241900Sdimthread::operator=(thread&& __t) _NOEXCEPT 392227825Stheraven{ 393227825Stheraven if (__t_ != 0) 394227825Stheraven terminate(); 395227825Stheraven __t_ = __t.__t_; 396227825Stheraven __t.__t_ = 0; 397227825Stheraven return *this; 398227825Stheraven} 399227825Stheraven 400227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 401227825Stheraven 402227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 403241900Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 404227825Stheraven 405227825Stheravennamespace this_thread 406227825Stheraven{ 407227825Stheraven 408227825Stheravenvoid sleep_for(const chrono::nanoseconds& ns); 409227825Stheraven 410227825Stheraventemplate <class _Rep, class _Period> 411227825Stheravenvoid 412227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d) 413227825Stheraven{ 414227825Stheraven using namespace chrono; 415241900Sdim if (__d > duration<_Rep, _Period>::zero()) 416241900Sdim { 417241900Sdim _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 418241900Sdim nanoseconds __ns; 419241900Sdim if (__d < _Max) 420241900Sdim { 421241900Sdim __ns = duration_cast<nanoseconds>(__d); 422241900Sdim if (__ns < __d) 423241900Sdim ++__ns; 424241900Sdim } 425241900Sdim else 426241900Sdim __ns = nanoseconds::max(); 427241900Sdim sleep_for(__ns); 428241900Sdim } 429227825Stheraven} 430227825Stheraven 431227825Stheraventemplate <class _Clock, class _Duration> 432227825Stheravenvoid 433227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t) 434227825Stheraven{ 435227825Stheraven using namespace chrono; 436227825Stheraven mutex __mut; 437227825Stheraven condition_variable __cv; 438227825Stheraven unique_lock<mutex> __lk(__mut); 439227825Stheraven while (_Clock::now() < __t) 440227825Stheraven __cv.wait_until(__lk, __t); 441227825Stheraven} 442227825Stheraven 443227825Stheraventemplate <class _Duration> 444227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 445227825Stheravenvoid 446227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 447227825Stheraven{ 448227825Stheraven using namespace chrono; 449227825Stheraven sleep_for(__t - steady_clock::now()); 450227825Stheraven} 451227825Stheraven 452227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 453241900Sdimvoid yield() _NOEXCEPT {sched_yield();} 454227825Stheraven 455227825Stheraven} // this_thread 456227825Stheraven 457227825Stheraven_LIBCPP_END_NAMESPACE_STD 458227825Stheraven 459227825Stheraven#endif // _LIBCPP_THREAD 460