thread revision 227825
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 29227825Stheraven thread(); 30227825Stheraven template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 31227825Stheraven ~thread(); 32227825Stheraven 33227825Stheraven thread(const thread&) = delete; 34227825Stheraven thread(thread&& t); 35227825Stheraven 36227825Stheraven thread& operator=(const thread&) = delete; 37227825Stheraven thread& operator=(thread&& t); 38227825Stheraven 39227825Stheraven void swap(thread& t); 40227825Stheraven 41227825Stheraven bool joinable() const; 42227825Stheraven void join(); 43227825Stheraven void detach(); 44227825Stheraven id get_id() const; 45227825Stheraven native_handle_type native_handle(); 46227825Stheraven 47227825Stheraven static unsigned hardware_concurrency(); 48227825Stheraven}; 49227825Stheraven 50227825Stheravenvoid swap(thread& x, thread& y); 51227825Stheraven 52227825Stheravenclass thread::id 53227825Stheraven{ 54227825Stheravenpublic: 55227825Stheraven id(); 56227825Stheraven}; 57227825Stheraven 58227825Stheravenbool operator==(thread::id x, thread::id y); 59227825Stheravenbool operator!=(thread::id x, thread::id y); 60227825Stheravenbool operator< (thread::id x, thread::id y); 61227825Stheravenbool operator<=(thread::id x, thread::id y); 62227825Stheravenbool operator> (thread::id x, thread::id y); 63227825Stheravenbool operator>=(thread::id x, thread::id y); 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 72227825Stheraventhread::id get_id(); 73227825Stheraven 74227825Stheravenvoid yield(); 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); 147227825Stheraven if (__ec) 148227825Stheraven throw system_error(error_code(__ec, system_category()), 149227825Stheraven "__thread_specific_ptr construction failed"); 150227825Stheraven} 151227825Stheraven 152227825Stheraventemplate <class _Tp> 153227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 154227825Stheraven{ 155227825Stheraven pthread_key_delete(__key_); 156227825Stheraven} 157227825Stheraven 158227825Stheraventemplate <class _Tp> 159227825Stheraventypename __thread_specific_ptr<_Tp>::pointer 160227825Stheraven__thread_specific_ptr<_Tp>::release() 161227825Stheraven{ 162227825Stheraven pointer __p = get(); 163227825Stheraven pthread_setspecific(__key_, 0); 164227825Stheraven return __p; 165227825Stheraven} 166227825Stheraven 167227825Stheraventemplate <class _Tp> 168227825Stheravenvoid 169227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p) 170227825Stheraven{ 171227825Stheraven pointer __p_old = get(); 172227825Stheraven pthread_setspecific(__key_, __p); 173227825Stheraven delete __p_old; 174227825Stheraven} 175227825Stheraven 176227825Stheravenclass thread; 177227825Stheravenclass __thread_id; 178227825Stheraven 179227825Stheravennamespace this_thread 180227825Stheraven{ 181227825Stheraven 182227825Stheraven__thread_id get_id(); 183227825Stheraven 184227825Stheraven} // this_thread 185227825Stheraven 186227825Stheravenclass _LIBCPP_VISIBLE __thread_id 187227825Stheraven{ 188227825Stheraven // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 189227825Stheraven // NULL is the no-thread value on Darwin. Someone needs to check 190227825Stheraven // on other platforms. We assume 0 works everywhere for now. 191227825Stheraven pthread_t __id_; 192227825Stheraven 193227825Stheravenpublic: 194227825Stheraven _LIBCPP_INLINE_VISIBILITY 195227825Stheraven __thread_id() : __id_(0) {} 196227825Stheraven 197227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 198227825Stheraven bool operator==(__thread_id __x, __thread_id __y) 199227825Stheraven {return __x.__id_ == __y.__id_;} 200227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 201227825Stheraven bool operator!=(__thread_id __x, __thread_id __y) 202227825Stheraven {return !(__x == __y);} 203227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 204227825Stheraven bool operator< (__thread_id __x, __thread_id __y) 205227825Stheraven {return __x.__id_ < __y.__id_;} 206227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 207227825Stheraven bool operator<=(__thread_id __x, __thread_id __y) 208227825Stheraven {return !(__y < __x);} 209227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 210227825Stheraven bool operator> (__thread_id __x, __thread_id __y) 211227825Stheraven {return __y < __x ;} 212227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 213227825Stheraven bool operator>=(__thread_id __x, __thread_id __y) 214227825Stheraven {return !(__x < __y);} 215227825Stheraven 216227825Stheraven template<class _CharT, class _Traits> 217227825Stheraven friend 218227825Stheraven _LIBCPP_INLINE_VISIBILITY 219227825Stheraven basic_ostream<_CharT, _Traits>& 220227825Stheraven operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 221227825Stheraven {return __os << __id.__id_;} 222227825Stheraven 223227825Stheravenprivate: 224227825Stheraven _LIBCPP_INLINE_VISIBILITY 225227825Stheraven __thread_id(pthread_t __id) : __id_(__id) {} 226227825Stheraven 227227825Stheraven friend __thread_id this_thread::get_id(); 228227825Stheraven friend class _LIBCPP_VISIBLE thread; 229227825Stheraven}; 230227825Stheraven 231227825Stheraventemplate<class _Tp> struct hash; 232227825Stheraven 233227825Stheraventemplate<> 234227825Stheravenstruct _LIBCPP_VISIBLE hash<__thread_id> 235227825Stheraven : public unary_function<__thread_id, size_t> 236227825Stheraven{ 237227825Stheraven _LIBCPP_INLINE_VISIBILITY 238227825Stheraven size_t operator()(__thread_id __v) const 239227825Stheraven { 240227825Stheraven const size_t* const __p = reinterpret_cast<const size_t*>(&__v); 241227825Stheraven return *__p; 242227825Stheraven } 243227825Stheraven}; 244227825Stheraven 245227825Stheravennamespace this_thread 246227825Stheraven{ 247227825Stheraven 248227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 249227825Stheraven__thread_id 250227825Stheravenget_id() 251227825Stheraven{ 252227825Stheraven return pthread_self(); 253227825Stheraven} 254227825Stheraven 255227825Stheraven} // this_thread 256227825Stheraven 257227825Stheravenclass _LIBCPP_VISIBLE thread 258227825Stheraven{ 259227825Stheraven pthread_t __t_; 260227825Stheraven 261227825Stheraven thread(const thread&); 262227825Stheraven thread& operator=(const thread&); 263227825Stheravenpublic: 264227825Stheraven typedef __thread_id id; 265227825Stheraven typedef pthread_t native_handle_type; 266227825Stheraven 267227825Stheraven _LIBCPP_INLINE_VISIBILITY 268227825Stheraven thread() : __t_(0) {} 269227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 270227825Stheraven template <class _F, class ..._Args, 271227825Stheraven class = typename enable_if 272227825Stheraven < 273227825Stheraven !is_same<typename decay<_F>::type, thread>::value 274227825Stheraven >::type 275227825Stheraven > 276227825Stheraven explicit thread(_F&& __f, _Args&&... __args); 277227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 278227825Stheraven template <class _F> explicit thread(_F __f); 279227825Stheraven#endif 280227825Stheraven ~thread(); 281227825Stheraven 282227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 283227825Stheraven _LIBCPP_INLINE_VISIBILITY 284227825Stheraven thread(thread&& __t) : __t_(__t.__t_) {__t.__t_ = 0;} 285227825Stheraven thread& operator=(thread&& __t); 286227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 287227825Stheraven 288227825Stheraven _LIBCPP_INLINE_VISIBILITY 289227825Stheraven void swap(thread& __t) {_VSTD::swap(__t_, __t.__t_);} 290227825Stheraven 291227825Stheraven _LIBCPP_INLINE_VISIBILITY 292227825Stheraven bool joinable() const {return __t_ != 0;} 293227825Stheraven void join(); 294227825Stheraven void detach(); 295227825Stheraven _LIBCPP_INLINE_VISIBILITY 296227825Stheraven id get_id() const {return __t_;} 297227825Stheraven _LIBCPP_INLINE_VISIBILITY 298227825Stheraven native_handle_type native_handle() {return __t_;} 299227825Stheraven 300227825Stheraven static unsigned hardware_concurrency(); 301227825Stheraven}; 302227825Stheraven 303227825Stheravenclass __assoc_sub_state; 304227825Stheraven 305227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp; 306227825Stheraven 307227825Stheravenclass __thread_struct 308227825Stheraven{ 309227825Stheraven __thread_struct_imp* __p_; 310227825Stheraven 311227825Stheraven __thread_struct(const __thread_struct&); 312227825Stheraven __thread_struct& operator=(const __thread_struct&); 313227825Stheravenpublic: 314227825Stheraven __thread_struct(); 315227825Stheraven ~__thread_struct(); 316227825Stheraven 317227825Stheraven void notify_all_at_thread_exit(condition_variable*, mutex*); 318227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state*); 319227825Stheraven}; 320227825Stheraven 321227825Stheraven__thread_specific_ptr<__thread_struct>& __thread_local_data(); 322227825Stheraven 323227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 324227825Stheraven 325227825Stheraventemplate <class _F, class ..._Args, size_t ..._Indices> 326227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 327227825Stheravenvoid 328227825Stheraven__threaad_execute(tuple<_F, _Args...>& __t, __tuple_indices<_Indices...>) 329227825Stheraven{ 330227825Stheraven __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 331227825Stheraven} 332227825Stheraven 333227825Stheraventemplate <class _F> 334227825Stheravenvoid* 335227825Stheraven__thread_proxy(void* __vp) 336227825Stheraven{ 337227825Stheraven __thread_local_data().reset(new __thread_struct); 338227825Stheraven std::unique_ptr<_F> __p(static_cast<_F*>(__vp)); 339227825Stheraven typedef typename __make_tuple_indices<tuple_size<_F>::value, 1>::type _Index; 340227825Stheraven __threaad_execute(*__p, _Index()); 341227825Stheraven return nullptr; 342227825Stheraven} 343227825Stheraven 344227825Stheraventemplate <class _F, class ..._Args, 345227825Stheraven class 346227825Stheraven > 347227825Stheraventhread::thread(_F&& __f, _Args&&... __args) 348227825Stheraven{ 349227825Stheraven typedef tuple<typename decay<_F>::type, typename decay<_Args>::type...> _G; 350227825Stheraven _VSTD::unique_ptr<_G> __p(new _G(__decay_copy(_VSTD::forward<_F>(__f)), 351227825Stheraven __decay_copy(_VSTD::forward<_Args>(__args))...)); 352227825Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_G>, __p.get()); 353227825Stheraven if (__ec == 0) 354227825Stheraven __p.release(); 355227825Stheraven else 356227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 357227825Stheraven} 358227825Stheraven 359227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 360227825Stheraven 361227825Stheraventemplate <class _F> 362227825Stheravenvoid* 363227825Stheraven__thread_proxy(void* __vp) 364227825Stheraven{ 365227825Stheraven __thread_local_data().reset(new __thread_struct); 366227825Stheraven std::unique_ptr<_F> __p(static_cast<_F*>(__vp)); 367227825Stheraven (*__p)(); 368227825Stheraven return nullptr; 369227825Stheraven} 370227825Stheraven 371227825Stheraventemplate <class _F> 372227825Stheraventhread::thread(_F __f) 373227825Stheraven{ 374227825Stheraven std::unique_ptr<_F> __p(new _F(__f)); 375227825Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_F>, __p.get()); 376227825Stheraven if (__ec == 0) 377227825Stheraven __p.release(); 378227825Stheraven else 379227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 380227825Stheraven} 381227825Stheraven 382227825Stheraven#endif // _LIBCPP_HAS_NO_VARIADICS 383227825Stheraven 384227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 385227825Stheraven 386227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 387227825Stheraventhread& 388227825Stheraventhread::operator=(thread&& __t) 389227825Stheraven{ 390227825Stheraven if (__t_ != 0) 391227825Stheraven terminate(); 392227825Stheraven __t_ = __t.__t_; 393227825Stheraven __t.__t_ = 0; 394227825Stheraven return *this; 395227825Stheraven} 396227825Stheraven 397227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 398227825Stheraven 399227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 400227825Stheravenvoid swap(thread& __x, thread& __y) {__x.swap(__y);} 401227825Stheraven 402227825Stheravennamespace this_thread 403227825Stheraven{ 404227825Stheraven 405227825Stheravenvoid sleep_for(const chrono::nanoseconds& ns); 406227825Stheraven 407227825Stheraventemplate <class _Rep, class _Period> 408227825Stheravenvoid 409227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d) 410227825Stheraven{ 411227825Stheraven using namespace chrono; 412227825Stheraven nanoseconds __ns = duration_cast<nanoseconds>(__d); 413227825Stheraven if (__ns < __d) 414227825Stheraven ++__ns; 415227825Stheraven sleep_for(__ns); 416227825Stheraven} 417227825Stheraven 418227825Stheraventemplate <class _Clock, class _Duration> 419227825Stheravenvoid 420227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t) 421227825Stheraven{ 422227825Stheraven using namespace chrono; 423227825Stheraven mutex __mut; 424227825Stheraven condition_variable __cv; 425227825Stheraven unique_lock<mutex> __lk(__mut); 426227825Stheraven while (_Clock::now() < __t) 427227825Stheraven __cv.wait_until(__lk, __t); 428227825Stheraven} 429227825Stheraven 430227825Stheraventemplate <class _Duration> 431227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 432227825Stheravenvoid 433227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 434227825Stheraven{ 435227825Stheraven using namespace chrono; 436227825Stheraven sleep_for(__t - steady_clock::now()); 437227825Stheraven} 438227825Stheraven 439227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 440227825Stheravenvoid yield() {sched_yield();} 441227825Stheraven 442227825Stheraven} // this_thread 443227825Stheraven 444227825Stheraven_LIBCPP_END_NAMESPACE_STD 445227825Stheraven 446227825Stheraven#endif // _LIBCPP_THREAD 447