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 <pthread.h> 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> 116class __thread_specific_ptr 117{ 118 pthread_key_t __key_; 119 120 __thread_specific_ptr(const __thread_specific_ptr&); 121 __thread_specific_ptr& operator=(const __thread_specific_ptr&); 122 123 static void __at_thread_exit(void*); 124public: 125 typedef _Tp* pointer; 126 127 __thread_specific_ptr(); 128 ~__thread_specific_ptr(); 129 130 _LIBCPP_INLINE_VISIBILITY 131 pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} 132 _LIBCPP_INLINE_VISIBILITY 133 pointer operator*() const {return *get();} 134 _LIBCPP_INLINE_VISIBILITY 135 pointer operator->() const {return get();} 136 pointer release(); 137 void reset(pointer __p = nullptr); 138}; 139 140template <class _Tp> 141void 142__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 143{ 144 delete static_cast<pointer>(__p); 145} 146 147template <class _Tp> 148__thread_specific_ptr<_Tp>::__thread_specific_ptr() 149{ 150 int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 151#ifndef _LIBCPP_NO_EXCEPTIONS 152 if (__ec) 153 throw system_error(error_code(__ec, system_category()), 154 "__thread_specific_ptr construction failed"); 155#endif 156} 157 158template <class _Tp> 159__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 160{ 161 pthread_key_delete(__key_); 162} 163 164template <class _Tp> 165typename __thread_specific_ptr<_Tp>::pointer 166__thread_specific_ptr<_Tp>::release() 167{ 168 pointer __p = get(); 169 pthread_setspecific(__key_, 0); 170 return __p; 171} 172 173template <class _Tp> 174void 175__thread_specific_ptr<_Tp>::reset(pointer __p) 176{ 177 pointer __p_old = get(); 178 pthread_setspecific(__key_, __p); 179 delete __p_old; 180} 181 182class _LIBCPP_TYPE_VIS thread; 183class _LIBCPP_TYPE_VIS __thread_id; 184 185namespace this_thread 186{ 187 188_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 189 190} // this_thread 191 192template<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 193 194class _LIBCPP_TYPE_VIS_ONLY __thread_id 195{ 196 // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 197 // NULL is the no-thread value on Darwin. Someone needs to check 198 // on other platforms. We assume 0 works everywhere for now. 199 pthread_t __id_; 200 201public: 202 _LIBCPP_INLINE_VISIBILITY 203 __thread_id() _NOEXCEPT : __id_(0) {} 204 205 friend _LIBCPP_INLINE_VISIBILITY 206 bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 207 {return __x.__id_ == __y.__id_;} 208 friend _LIBCPP_INLINE_VISIBILITY 209 bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 210 {return !(__x == __y);} 211 friend _LIBCPP_INLINE_VISIBILITY 212 bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 213 {return __x.__id_ < __y.__id_;} 214 friend _LIBCPP_INLINE_VISIBILITY 215 bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 216 {return !(__y < __x);} 217 friend _LIBCPP_INLINE_VISIBILITY 218 bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 219 {return __y < __x ;} 220 friend _LIBCPP_INLINE_VISIBILITY 221 bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 222 {return !(__x < __y);} 223 224 template<class _CharT, class _Traits> 225 friend 226 _LIBCPP_INLINE_VISIBILITY 227 basic_ostream<_CharT, _Traits>& 228 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 229 {return __os << __id.__id_;} 230 231private: 232 _LIBCPP_INLINE_VISIBILITY 233 __thread_id(pthread_t __id) : __id_(__id) {} 234 235 friend __thread_id this_thread::get_id() _NOEXCEPT; 236 friend class _LIBCPP_TYPE_VIS thread; 237 friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 238}; 239 240template<> 241struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> 242 : public unary_function<__thread_id, size_t> 243{ 244 _LIBCPP_INLINE_VISIBILITY 245 size_t operator()(__thread_id __v) const 246 { 247 return hash<pthread_t>()(__v.__id_); 248 } 249}; 250 251namespace this_thread 252{ 253 254inline _LIBCPP_INLINE_VISIBILITY 255__thread_id 256get_id() _NOEXCEPT 257{ 258 return pthread_self(); 259} 260 261} // this_thread 262 263class _LIBCPP_TYPE_VIS thread 264{ 265 pthread_t __t_; 266 267 thread(const thread&); 268 thread& operator=(const thread&); 269public: 270 typedef __thread_id id; 271 typedef pthread_t native_handle_type; 272 273 _LIBCPP_INLINE_VISIBILITY 274 thread() _NOEXCEPT : __t_(0) {} 275#ifndef _LIBCPP_HAS_NO_VARIADICS 276 template <class _Fp, class ..._Args, 277 class = typename enable_if 278 < 279 !is_same<typename decay<_Fp>::type, thread>::value 280 >::type 281 > 282 explicit thread(_Fp&& __f, _Args&&... __args); 283#else // _LIBCPP_HAS_NO_VARIADICS 284 template <class _Fp> explicit thread(_Fp __f); 285#endif 286 ~thread(); 287 288#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 289 _LIBCPP_INLINE_VISIBILITY 290 thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 291 thread& operator=(thread&& __t) _NOEXCEPT; 292#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 293 294 _LIBCPP_INLINE_VISIBILITY 295 void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 296 297 _LIBCPP_INLINE_VISIBILITY 298 bool joinable() const _NOEXCEPT {return __t_ != 0;} 299 void join(); 300 void detach(); 301 _LIBCPP_INLINE_VISIBILITY 302 id get_id() const _NOEXCEPT {return __t_;} 303 _LIBCPP_INLINE_VISIBILITY 304 native_handle_type native_handle() _NOEXCEPT {return __t_;} 305 306 static unsigned hardware_concurrency() _NOEXCEPT; 307}; 308 309class __assoc_sub_state; 310 311class _LIBCPP_HIDDEN __thread_struct_imp; 312 313class _LIBCPP_TYPE_VIS __thread_struct 314{ 315 __thread_struct_imp* __p_; 316 317 __thread_struct(const __thread_struct&); 318 __thread_struct& operator=(const __thread_struct&); 319public: 320 __thread_struct(); 321 ~__thread_struct(); 322 323 void notify_all_at_thread_exit(condition_variable*, mutex*); 324 void __make_ready_at_thread_exit(__assoc_sub_state*); 325}; 326 327_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 328 329#ifndef _LIBCPP_HAS_NO_VARIADICS 330 331template <class _Fp, class ..._Args, size_t ..._Indices> 332inline _LIBCPP_INLINE_VISIBILITY 333void 334__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) 335{ 336 __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 337} 338 339template <class _Fp> 340void* 341__thread_proxy(void* __vp) 342{ 343 __thread_local_data().reset(new __thread_struct); 344 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 345 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 346 __thread_execute(*__p, _Index()); 347 return nullptr; 348} 349 350template <class _Fp, class ..._Args, 351 class 352 > 353thread::thread(_Fp&& __f, _Args&&... __args) 354{ 355 typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 356 _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), 357 __decay_copy(_VSTD::forward<_Args>(__args))...)); 358 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 359 if (__ec == 0) 360 __p.release(); 361 else 362 __throw_system_error(__ec, "thread constructor failed"); 363} 364 365#else // _LIBCPP_HAS_NO_VARIADICS 366 367template <class _Fp> 368void* 369__thread_proxy(void* __vp) 370{ 371 __thread_local_data().reset(new __thread_struct); 372 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 373 (*__p)(); 374 return nullptr; 375} 376 377template <class _Fp> 378thread::thread(_Fp __f) 379{ 380 std::unique_ptr<_Fp> __p(new _Fp(__f)); 381 int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); 382 if (__ec == 0) 383 __p.release(); 384 else 385 __throw_system_error(__ec, "thread constructor failed"); 386} 387 388#endif // _LIBCPP_HAS_NO_VARIADICS 389 390#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 391 392inline _LIBCPP_INLINE_VISIBILITY 393thread& 394thread::operator=(thread&& __t) _NOEXCEPT 395{ 396 if (__t_ != 0) 397 terminate(); 398 __t_ = __t.__t_; 399 __t.__t_ = 0; 400 return *this; 401} 402 403#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 404 405inline _LIBCPP_INLINE_VISIBILITY 406void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 407 408namespace this_thread 409{ 410 411_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns); 412 413template <class _Rep, class _Period> 414void 415sleep_for(const chrono::duration<_Rep, _Period>& __d) 416{ 417 using namespace chrono; 418 if (__d > duration<_Rep, _Period>::zero()) 419 { 420 _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 421 nanoseconds __ns; 422 if (__d < _Max) 423 { 424 __ns = duration_cast<nanoseconds>(__d); 425 if (__ns < __d) 426 ++__ns; 427 } 428 else 429 __ns = nanoseconds::max(); 430 sleep_for(__ns); 431 } 432} 433 434template <class _Clock, class _Duration> 435void 436sleep_until(const chrono::time_point<_Clock, _Duration>& __t) 437{ 438 using namespace chrono; 439 mutex __mut; 440 condition_variable __cv; 441 unique_lock<mutex> __lk(__mut); 442 while (_Clock::now() < __t) 443 __cv.wait_until(__lk, __t); 444} 445 446template <class _Duration> 447inline _LIBCPP_INLINE_VISIBILITY 448void 449sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 450{ 451 using namespace chrono; 452 sleep_for(__t - steady_clock::now()); 453} 454 455inline _LIBCPP_INLINE_VISIBILITY 456void yield() _NOEXCEPT {sched_yield();} 457 458} // this_thread 459 460_LIBCPP_END_NAMESPACE_STD 461 462#endif // !_LIBCPP_HAS_NO_THREADS 463 464#endif // _LIBCPP_THREAD 465