1// -*- C++ -*- 2//===--------------------------- thread -----------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_THREAD 12#define _LIBCPP_THREAD 13 14/* 15 16 thread synopsis 17 18#define __STDCPP_THREADS__ __cplusplus 19 20namespace std 21{ 22 23class thread 24{ 25public: 26 class id; 27 typedef pthread_t native_handle_type; 28 29 thread() noexcept; 30 template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 31 ~thread(); 32 33 thread(const thread&) = delete; 34 thread(thread&& t) noexcept; 35 36 thread& operator=(const thread&) = delete; 37 thread& operator=(thread&& t) noexcept; 38 39 void swap(thread& t) noexcept; 40 41 bool joinable() const noexcept; 42 void join(); 43 void detach(); 44 id get_id() const noexcept; 45 native_handle_type native_handle(); 46 47 static unsigned hardware_concurrency() noexcept; 48}; 49 50void swap(thread& x, thread& y) noexcept; 51 52class thread::id 53{ 54public: 55 id() noexcept; 56}; 57 58bool operator==(thread::id x, thread::id y) noexcept; 59bool operator!=(thread::id x, thread::id y) noexcept; 60bool operator< (thread::id x, thread::id y) noexcept; 61bool operator<=(thread::id x, thread::id y) noexcept; 62bool operator> (thread::id x, thread::id y) noexcept; 63bool operator>=(thread::id x, thread::id y) noexcept; 64 65template<class charT, class traits> 66basic_ostream<charT, traits>& 67operator<<(basic_ostream<charT, traits>& out, thread::id id); 68 69namespace this_thread 70{ 71 72thread::id get_id() noexcept; 73 74void yield() noexcept; 75 76template <class Clock, class Duration> 77void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); 78 79template <class Rep, class Period> 80void sleep_for(const chrono::duration<Rep, Period>& rel_time); 81 82} // this_thread 83 84} // std 85 86*/ 87 88#include <__config> 89#include <iosfwd> 90#include <__functional_base> 91#include <type_traits> 92#include <cstddef> 93#include <functional> 94#include <memory> 95#include <system_error> 96#include <chrono> 97#include <__mutex_base> 98#ifndef _LIBCPP_HAS_NO_VARIADICS 99#include <tuple> 100#endif 101#include <__threading_support> 102 103#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 104#pragma GCC system_header 105#endif 106 107#define __STDCPP_THREADS__ __cplusplus 108 109#ifdef _LIBCPP_HAS_NO_THREADS 110#error <thread> is not supported on this single threaded system 111#else // !_LIBCPP_HAS_NO_THREADS 112 113_LIBCPP_BEGIN_NAMESPACE_STD 114 115template <class _Tp> class __thread_specific_ptr; 116class _LIBCPP_TYPE_VIS __thread_struct; 117class _LIBCPP_HIDDEN __thread_struct_imp; 118class __assoc_sub_state; 119 120_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 121 122class _LIBCPP_TYPE_VIS __thread_struct 123{ 124 __thread_struct_imp* __p_; 125 126 __thread_struct(const __thread_struct&); 127 __thread_struct& operator=(const __thread_struct&); 128public: 129 __thread_struct(); 130 ~__thread_struct(); 131 132 void notify_all_at_thread_exit(condition_variable*, mutex*); 133 void __make_ready_at_thread_exit(__assoc_sub_state*); 134}; 135 136template <class _Tp> 137class __thread_specific_ptr 138{ 139 __libcpp_tl_key __key_; 140 141 // Only __thread_local_data() may construct a __thread_specific_ptr 142 // and only with _Tp == __thread_struct. 143 static_assert((is_same<_Tp, __thread_struct>::value), ""); 144 __thread_specific_ptr(); 145 friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 146 147 __thread_specific_ptr(const __thread_specific_ptr&); 148 __thread_specific_ptr& operator=(const __thread_specific_ptr&); 149 150 static void __at_thread_exit(void*); 151public: 152 typedef _Tp* pointer; 153 154 ~__thread_specific_ptr(); 155 156 _LIBCPP_INLINE_VISIBILITY 157 pointer get() const {return static_cast<_Tp*>(__libcpp_tl_get(__key_));} 158 _LIBCPP_INLINE_VISIBILITY 159 pointer operator*() const {return *get();} 160 _LIBCPP_INLINE_VISIBILITY 161 pointer operator->() const {return get();} 162 pointer release(); 163 void reset(pointer __p = nullptr); 164}; 165 166template <class _Tp> 167void 168__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 169{ 170 delete static_cast<pointer>(__p); 171} 172 173template <class _Tp> 174__thread_specific_ptr<_Tp>::__thread_specific_ptr() 175{ 176 int __ec = __libcpp_tl_create( 177 &__key_, 178 &__thread_specific_ptr::__at_thread_exit); 179 if (__ec) 180 __throw_system_error(__ec, 181 "__thread_specific_ptr construction failed"); 182} 183 184template <class _Tp> 185__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 186{ 187 // __thread_specific_ptr is only created with a static storage duration 188 // so this destructor is only invoked during program termination. Invoking 189 // pthread_key_delete(__key_) may prevent other threads from deleting their 190 // thread local data. For this reason we leak the key. 191} 192 193template <class _Tp> 194typename __thread_specific_ptr<_Tp>::pointer 195__thread_specific_ptr<_Tp>::release() 196{ 197 pointer __p = get(); 198 __libcpp_tl_set(__key_, nullptr); 199 return __p; 200} 201 202template <class _Tp> 203void 204__thread_specific_ptr<_Tp>::reset(pointer __p) 205{ 206 pointer __p_old = get(); 207 __libcpp_tl_set(__key_, __p); 208 delete __p_old; 209} 210 211class _LIBCPP_TYPE_VIS thread; 212class _LIBCPP_TYPE_VIS __thread_id; 213 214namespace this_thread 215{ 216 217_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 218 219} // this_thread 220 221template<> struct hash<__thread_id>; 222 223class _LIBCPP_TYPE_VIS_ONLY __thread_id 224{ 225 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 226 // NULL is the no-thread value on Darwin. Someone needs to check 227 // on other platforms. We assume 0 works everywhere for now. 228 __libcpp_thread_id __id_; 229 230public: 231 _LIBCPP_INLINE_VISIBILITY 232 __thread_id() _NOEXCEPT : __id_(0) {} 233 234 friend _LIBCPP_INLINE_VISIBILITY 235 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 236 {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);} 237 friend _LIBCPP_INLINE_VISIBILITY 238 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 239 {return !(__x == __y);} 240 friend _LIBCPP_INLINE_VISIBILITY 241 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 242 {return __libcpp_thread_id_less(__x.__id_, __y.__id_);} 243 friend _LIBCPP_INLINE_VISIBILITY 244 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 245 {return !(__y < __x);} 246 friend _LIBCPP_INLINE_VISIBILITY 247 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 248 {return __y < __x ;} 249 friend _LIBCPP_INLINE_VISIBILITY 250 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 251 {return !(__x < __y);} 252 253 template<class _CharT, class _Traits> 254 friend 255 _LIBCPP_INLINE_VISIBILITY 256 basic_ostream<_CharT, _Traits>& 257 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 258 {return __os << __id.__id_;} 259 260private: 261 _LIBCPP_INLINE_VISIBILITY 262 __thread_id(__libcpp_thread_id __id) : __id_(__id) {} 263 264 friend __thread_id this_thread::get_id() _NOEXCEPT; 265 friend class _LIBCPP_TYPE_VIS thread; 266 friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 267}; 268 269template<> 270struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> 271 : public unary_function<__thread_id, size_t> 272{ 273 _LIBCPP_INLINE_VISIBILITY 274 size_t operator()(__thread_id __v) const 275 { 276 return hash<__libcpp_thread_id>()(__v.__id_); 277 } 278}; 279 280namespace this_thread 281{ 282 283inline _LIBCPP_INLINE_VISIBILITY 284__thread_id 285get_id() _NOEXCEPT 286{ 287 return __libcpp_thread_get_current_id(); 288} 289 290} // this_thread 291 292class _LIBCPP_TYPE_VIS thread 293{ 294 __libcpp_thread_t __t_; 295 296 thread(const thread&); 297 thread& operator=(const thread&); 298public: 299 typedef __thread_id id; 300 typedef __libcpp_thread_t native_handle_type; 301 302 _LIBCPP_INLINE_VISIBILITY 303 thread() _NOEXCEPT : __t_(0) {} 304#ifndef _LIBCPP_HAS_NO_VARIADICS 305 template <class _Fp, class ..._Args, 306 class = typename enable_if 307 < 308 !is_same<typename decay<_Fp>::type, thread>::value 309 >::type 310 > 311 explicit thread(_Fp&& __f, _Args&&... __args); 312#else // _LIBCPP_HAS_NO_VARIADICS 313 template <class _Fp> explicit thread(_Fp __f); 314#endif 315 ~thread(); 316 317#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 318 _LIBCPP_INLINE_VISIBILITY 319 thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 320 _LIBCPP_INLINE_VISIBILITY 321 thread& operator=(thread&& __t) _NOEXCEPT; 322#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 323 324 _LIBCPP_INLINE_VISIBILITY 325 void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 326 327 _LIBCPP_INLINE_VISIBILITY 328 bool joinable() const _NOEXCEPT {return __t_ != 0;} 329 void join(); 330 void detach(); 331 _LIBCPP_INLINE_VISIBILITY 332 id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} 333 _LIBCPP_INLINE_VISIBILITY 334 native_handle_type native_handle() _NOEXCEPT {return __t_;} 335 336 static unsigned hardware_concurrency() _NOEXCEPT; 337}; 338 339#ifndef _LIBCPP_HAS_NO_VARIADICS 340 341template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> 342inline _LIBCPP_INLINE_VISIBILITY 343void 344__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) 345{ 346 __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 347} 348 349template <class _Fp> 350void* __thread_proxy(void* __vp) 351{ 352 // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> 353 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 354 __thread_local_data().reset(_VSTD::get<0>(*__p).release()); 355 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; 356 __thread_execute(*__p, _Index()); 357 return nullptr; 358} 359 360template <class _Fp, class ..._Args, 361 class 362 > 363thread::thread(_Fp&& __f, _Args&&... __args) 364{ 365 typedef unique_ptr<__thread_struct> _TSPtr; 366 _TSPtr __tsp(new __thread_struct); 367 typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 368 _VSTD::unique_ptr<_Gp> __p( 369 new _Gp(std::move(__tsp), 370 __decay_copy(_VSTD::forward<_Fp>(__f)), 371 __decay_copy(_VSTD::forward<_Args>(__args))...)); 372 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); 373 if (__ec == 0) 374 __p.release(); 375 else 376 __throw_system_error(__ec, "thread constructor failed"); 377} 378 379#else // _LIBCPP_HAS_NO_VARIADICS 380 381template <class _Fp> 382struct __thread_invoke_pair { 383 // This type is used to pass memory for thread local storage and a functor 384 // to a newly created thread because std::pair doesn't work with 385 // std::unique_ptr in C++03. 386 __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} 387 unique_ptr<__thread_struct> __tsp_; 388 _Fp __fn_; 389}; 390 391template <class _Fp> 392void* __thread_proxy_cxx03(void* __vp) 393{ 394 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 395 __thread_local_data().reset(__p->__tsp_.release()); 396 (__p->__fn_)(); 397 return nullptr; 398} 399 400template <class _Fp> 401thread::thread(_Fp __f) 402{ 403 404 typedef __thread_invoke_pair<_Fp> _InvokePair; 405 typedef std::unique_ptr<_InvokePair> _PairPtr; 406 _PairPtr __pp(new _InvokePair(__f)); 407 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); 408 if (__ec == 0) 409 __pp.release(); 410 else 411 __throw_system_error(__ec, "thread constructor failed"); 412} 413 414#endif // _LIBCPP_HAS_NO_VARIADICS 415 416#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 417 418inline 419thread& 420thread::operator=(thread&& __t) _NOEXCEPT 421{ 422 if (__t_ != 0) 423 terminate(); 424 __t_ = __t.__t_; 425 __t.__t_ = 0; 426 return *this; 427} 428 429#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 430 431inline _LIBCPP_INLINE_VISIBILITY 432void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 433 434namespace this_thread 435{ 436 437_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns); 438 439template <class _Rep, class _Period> 440void 441sleep_for(const chrono::duration<_Rep, _Period>& __d) 442{ 443 using namespace chrono; 444 if (__d > duration<_Rep, _Period>::zero()) 445 { 446 _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 447 nanoseconds __ns; 448 if (__d < _Max) 449 { 450 __ns = duration_cast<nanoseconds>(__d); 451 if (__ns < __d) 452 ++__ns; 453 } 454 else 455 __ns = nanoseconds::max(); 456 sleep_for(__ns); 457 } 458} 459 460template <class _Clock, class _Duration> 461void 462sleep_until(const chrono::time_point<_Clock, _Duration>& __t) 463{ 464 using namespace chrono; 465 mutex __mut; 466 condition_variable __cv; 467 unique_lock<mutex> __lk(__mut); 468 while (_Clock::now() < __t) 469 __cv.wait_until(__lk, __t); 470} 471 472template <class _Duration> 473inline _LIBCPP_INLINE_VISIBILITY 474void 475sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 476{ 477 using namespace chrono; 478 sleep_for(__t - steady_clock::now()); 479} 480 481inline _LIBCPP_INLINE_VISIBILITY 482void yield() _NOEXCEPT {__libcpp_thread_yield();} 483 484} // this_thread 485 486_LIBCPP_END_NAMESPACE_STD 487 488#endif // !_LIBCPP_HAS_NO_THREADS 489 490#endif // _LIBCPP_THREAD 491