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 29241903Sdim thread() noexcept; 30227825Stheraven template <class F, class ...Args> explicit thread(F&& f, Args&&... args); 31227825Stheraven ~thread(); 32227825Stheraven 33227825Stheraven thread(const thread&) = delete; 34241903Sdim thread(thread&& t) noexcept; 35227825Stheraven 36227825Stheraven thread& operator=(const thread&) = delete; 37241903Sdim thread& operator=(thread&& t) noexcept; 38227825Stheraven 39241903Sdim void swap(thread& t) noexcept; 40227825Stheraven 41241903Sdim bool joinable() const noexcept; 42227825Stheraven void join(); 43227825Stheraven void detach(); 44241903Sdim id get_id() const noexcept; 45227825Stheraven native_handle_type native_handle(); 46227825Stheraven 47241903Sdim static unsigned hardware_concurrency() noexcept; 48227825Stheraven}; 49227825Stheraven 50241903Sdimvoid swap(thread& x, thread& y) noexcept; 51227825Stheraven 52227825Stheravenclass thread::id 53227825Stheraven{ 54227825Stheravenpublic: 55241903Sdim id() noexcept; 56227825Stheraven}; 57227825Stheraven 58241903Sdimbool operator==(thread::id x, thread::id y) noexcept; 59241903Sdimbool operator!=(thread::id x, thread::id y) noexcept; 60241903Sdimbool operator< (thread::id x, thread::id y) noexcept; 61241903Sdimbool operator<=(thread::id x, thread::id y) noexcept; 62241903Sdimbool operator> (thread::id x, thread::id y) noexcept; 63241903Sdimbool 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 72241903Sdimthread::id get_id() noexcept; 73227825Stheraven 74241903Sdimvoid 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> 102278724Sdim#include <sched.h> 103227825Stheraven 104227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 105227825Stheraven#pragma GCC system_header 106227825Stheraven#endif 107227825Stheraven 108227825Stheraven#define __STDCPP_THREADS__ __cplusplus 109227825Stheraven 110278724Sdim#ifdef _LIBCPP_HAS_NO_THREADS 111278724Sdim#error <thread> is not supported on this single threaded system 112278724Sdim#else // !_LIBCPP_HAS_NO_THREADS 113278724Sdim 114227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 115227825Stheraven 116227825Stheraventemplate <class _Tp> 117227825Stheravenclass __thread_specific_ptr 118227825Stheraven{ 119227825Stheraven pthread_key_t __key_; 120227825Stheraven 121227825Stheraven __thread_specific_ptr(const __thread_specific_ptr&); 122227825Stheraven __thread_specific_ptr& operator=(const __thread_specific_ptr&); 123227825Stheraven 124227825Stheraven static void __at_thread_exit(void*); 125227825Stheravenpublic: 126227825Stheraven typedef _Tp* pointer; 127227825Stheraven 128227825Stheraven __thread_specific_ptr(); 129227825Stheraven ~__thread_specific_ptr(); 130227825Stheraven 131227825Stheraven _LIBCPP_INLINE_VISIBILITY 132227825Stheraven pointer get() const {return static_cast<_Tp*>(pthread_getspecific(__key_));} 133227825Stheraven _LIBCPP_INLINE_VISIBILITY 134227825Stheraven pointer operator*() const {return *get();} 135227825Stheraven _LIBCPP_INLINE_VISIBILITY 136227825Stheraven pointer operator->() const {return get();} 137227825Stheraven pointer release(); 138227825Stheraven void reset(pointer __p = nullptr); 139227825Stheraven}; 140227825Stheraven 141227825Stheraventemplate <class _Tp> 142227825Stheravenvoid 143227825Stheraven__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) 144227825Stheraven{ 145227825Stheraven delete static_cast<pointer>(__p); 146227825Stheraven} 147227825Stheraven 148227825Stheraventemplate <class _Tp> 149227825Stheraven__thread_specific_ptr<_Tp>::__thread_specific_ptr() 150227825Stheraven{ 151227825Stheraven int __ec = pthread_key_create(&__key_, &__thread_specific_ptr::__at_thread_exit); 152249998Sdim#ifndef _LIBCPP_NO_EXCEPTIONS 153227825Stheraven if (__ec) 154227825Stheraven throw system_error(error_code(__ec, system_category()), 155227825Stheraven "__thread_specific_ptr construction failed"); 156249998Sdim#endif 157227825Stheraven} 158227825Stheraven 159227825Stheraventemplate <class _Tp> 160227825Stheraven__thread_specific_ptr<_Tp>::~__thread_specific_ptr() 161227825Stheraven{ 162227825Stheraven pthread_key_delete(__key_); 163227825Stheraven} 164227825Stheraven 165227825Stheraventemplate <class _Tp> 166227825Stheraventypename __thread_specific_ptr<_Tp>::pointer 167227825Stheraven__thread_specific_ptr<_Tp>::release() 168227825Stheraven{ 169227825Stheraven pointer __p = get(); 170227825Stheraven pthread_setspecific(__key_, 0); 171227825Stheraven return __p; 172227825Stheraven} 173227825Stheraven 174227825Stheraventemplate <class _Tp> 175227825Stheravenvoid 176227825Stheraven__thread_specific_ptr<_Tp>::reset(pointer __p) 177227825Stheraven{ 178227825Stheraven pointer __p_old = get(); 179227825Stheraven pthread_setspecific(__key_, __p); 180227825Stheraven delete __p_old; 181227825Stheraven} 182227825Stheraven 183249998Sdimclass _LIBCPP_TYPE_VIS thread; 184249998Sdimclass _LIBCPP_TYPE_VIS __thread_id; 185227825Stheraven 186227825Stheravennamespace this_thread 187227825Stheraven{ 188227825Stheraven 189241903Sdim_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; 190227825Stheraven 191227825Stheraven} // this_thread 192227825Stheraven 193262801Sdimtemplate<> struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 194232950Stheraven 195262801Sdimclass _LIBCPP_TYPE_VIS_ONLY __thread_id 196227825Stheraven{ 197227825Stheraven // FIXME: pthread_t is a pointer on Darwin but a long on Linux. 198227825Stheraven // NULL is the no-thread value on Darwin. Someone needs to check 199227825Stheraven // on other platforms. We assume 0 works everywhere for now. 200227825Stheraven pthread_t __id_; 201227825Stheraven 202227825Stheravenpublic: 203227825Stheraven _LIBCPP_INLINE_VISIBILITY 204241903Sdim __thread_id() _NOEXCEPT : __id_(0) {} 205227825Stheraven 206227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 207241903Sdim bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT 208227825Stheraven {return __x.__id_ == __y.__id_;} 209227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 210241903Sdim bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT 211227825Stheraven {return !(__x == __y);} 212227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 213241903Sdim bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT 214227825Stheraven {return __x.__id_ < __y.__id_;} 215227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 216241903Sdim bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT 217227825Stheraven {return !(__y < __x);} 218227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 219241903Sdim bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT 220227825Stheraven {return __y < __x ;} 221227825Stheraven friend _LIBCPP_INLINE_VISIBILITY 222241903Sdim bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT 223227825Stheraven {return !(__x < __y);} 224227825Stheraven 225227825Stheraven template<class _CharT, class _Traits> 226227825Stheraven friend 227227825Stheraven _LIBCPP_INLINE_VISIBILITY 228227825Stheraven basic_ostream<_CharT, _Traits>& 229227825Stheraven operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 230227825Stheraven {return __os << __id.__id_;} 231227825Stheraven 232227825Stheravenprivate: 233227825Stheraven _LIBCPP_INLINE_VISIBILITY 234227825Stheraven __thread_id(pthread_t __id) : __id_(__id) {} 235227825Stheraven 236241903Sdim friend __thread_id this_thread::get_id() _NOEXCEPT; 237249998Sdim friend class _LIBCPP_TYPE_VIS thread; 238262801Sdim friend struct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id>; 239227825Stheraven}; 240227825Stheraven 241227825Stheraventemplate<> 242262801Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<__thread_id> 243227825Stheraven : public unary_function<__thread_id, size_t> 244227825Stheraven{ 245227825Stheraven _LIBCPP_INLINE_VISIBILITY 246227825Stheraven size_t operator()(__thread_id __v) const 247227825Stheraven { 248232950Stheraven return hash<pthread_t>()(__v.__id_); 249227825Stheraven } 250227825Stheraven}; 251227825Stheraven 252227825Stheravennamespace this_thread 253227825Stheraven{ 254227825Stheraven 255227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 256227825Stheraven__thread_id 257241903Sdimget_id() _NOEXCEPT 258227825Stheraven{ 259227825Stheraven return pthread_self(); 260227825Stheraven} 261227825Stheraven 262227825Stheraven} // this_thread 263227825Stheraven 264249998Sdimclass _LIBCPP_TYPE_VIS thread 265227825Stheraven{ 266227825Stheraven pthread_t __t_; 267227825Stheraven 268227825Stheraven thread(const thread&); 269227825Stheraven thread& operator=(const thread&); 270227825Stheravenpublic: 271227825Stheraven typedef __thread_id id; 272227825Stheraven typedef pthread_t native_handle_type; 273227825Stheraven 274227825Stheraven _LIBCPP_INLINE_VISIBILITY 275241903Sdim thread() _NOEXCEPT : __t_(0) {} 276227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 277232950Stheraven template <class _Fp, class ..._Args, 278227825Stheraven class = typename enable_if 279227825Stheraven < 280232950Stheraven !is_same<typename decay<_Fp>::type, thread>::value 281227825Stheraven >::type 282227825Stheraven > 283232950Stheraven explicit thread(_Fp&& __f, _Args&&... __args); 284227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 285232950Stheraven template <class _Fp> explicit thread(_Fp __f); 286227825Stheraven#endif 287227825Stheraven ~thread(); 288227825Stheraven 289227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 290227825Stheraven _LIBCPP_INLINE_VISIBILITY 291241903Sdim thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = 0;} 292241903Sdim thread& operator=(thread&& __t) _NOEXCEPT; 293227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 294227825Stheraven 295227825Stheraven _LIBCPP_INLINE_VISIBILITY 296241903Sdim void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 297227825Stheraven 298227825Stheraven _LIBCPP_INLINE_VISIBILITY 299241903Sdim bool joinable() const _NOEXCEPT {return __t_ != 0;} 300227825Stheraven void join(); 301227825Stheraven void detach(); 302227825Stheraven _LIBCPP_INLINE_VISIBILITY 303241903Sdim id get_id() const _NOEXCEPT {return __t_;} 304227825Stheraven _LIBCPP_INLINE_VISIBILITY 305241903Sdim native_handle_type native_handle() _NOEXCEPT {return __t_;} 306227825Stheraven 307241903Sdim static unsigned hardware_concurrency() _NOEXCEPT; 308227825Stheraven}; 309227825Stheraven 310227825Stheravenclass __assoc_sub_state; 311227825Stheraven 312227825Stheravenclass _LIBCPP_HIDDEN __thread_struct_imp; 313227825Stheraven 314262801Sdimclass _LIBCPP_TYPE_VIS __thread_struct 315227825Stheraven{ 316227825Stheraven __thread_struct_imp* __p_; 317227825Stheraven 318227825Stheraven __thread_struct(const __thread_struct&); 319227825Stheraven __thread_struct& operator=(const __thread_struct&); 320227825Stheravenpublic: 321227825Stheraven __thread_struct(); 322227825Stheraven ~__thread_struct(); 323227825Stheraven 324227825Stheraven void notify_all_at_thread_exit(condition_variable*, mutex*); 325227825Stheraven void __make_ready_at_thread_exit(__assoc_sub_state*); 326227825Stheraven}; 327227825Stheraven 328262801Sdim_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); 329227825Stheraven 330227825Stheraven#ifndef _LIBCPP_HAS_NO_VARIADICS 331227825Stheraven 332232950Stheraventemplate <class _Fp, class ..._Args, size_t ..._Indices> 333227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 334227825Stheravenvoid 335249998Sdim__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>) 336227825Stheraven{ 337227825Stheraven __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 338227825Stheraven} 339227825Stheraven 340232950Stheraventemplate <class _Fp> 341227825Stheravenvoid* 342227825Stheraven__thread_proxy(void* __vp) 343227825Stheraven{ 344227825Stheraven __thread_local_data().reset(new __thread_struct); 345232950Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 346232950Stheraven typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; 347249998Sdim __thread_execute(*__p, _Index()); 348227825Stheraven return nullptr; 349227825Stheraven} 350227825Stheraven 351232950Stheraventemplate <class _Fp, class ..._Args, 352227825Stheraven class 353227825Stheraven > 354232950Stheraventhread::thread(_Fp&& __f, _Args&&... __args) 355227825Stheraven{ 356232950Stheraven typedef tuple<typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 357232950Stheraven _VSTD::unique_ptr<_Gp> __p(new _Gp(__decay_copy(_VSTD::forward<_Fp>(__f)), 358227825Stheraven __decay_copy(_VSTD::forward<_Args>(__args))...)); 359232950Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get()); 360227825Stheraven if (__ec == 0) 361227825Stheraven __p.release(); 362227825Stheraven else 363227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 364227825Stheraven} 365227825Stheraven 366227825Stheraven#else // _LIBCPP_HAS_NO_VARIADICS 367227825Stheraven 368232950Stheraventemplate <class _Fp> 369227825Stheravenvoid* 370227825Stheraven__thread_proxy(void* __vp) 371227825Stheraven{ 372227825Stheraven __thread_local_data().reset(new __thread_struct); 373232950Stheraven std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 374227825Stheraven (*__p)(); 375227825Stheraven return nullptr; 376227825Stheraven} 377227825Stheraven 378232950Stheraventemplate <class _Fp> 379232950Stheraventhread::thread(_Fp __f) 380227825Stheraven{ 381232950Stheraven std::unique_ptr<_Fp> __p(new _Fp(__f)); 382232950Stheraven int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Fp>, __p.get()); 383227825Stheraven if (__ec == 0) 384227825Stheraven __p.release(); 385227825Stheraven else 386227825Stheraven __throw_system_error(__ec, "thread constructor failed"); 387227825Stheraven} 388227825Stheraven 389227825Stheraven#endif // _LIBCPP_HAS_NO_VARIADICS 390227825Stheraven 391227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 392227825Stheraven 393227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 394227825Stheraventhread& 395241903Sdimthread::operator=(thread&& __t) _NOEXCEPT 396227825Stheraven{ 397227825Stheraven if (__t_ != 0) 398227825Stheraven terminate(); 399227825Stheraven __t_ = __t.__t_; 400227825Stheraven __t.__t_ = 0; 401227825Stheraven return *this; 402227825Stheraven} 403227825Stheraven 404227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 405227825Stheraven 406227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 407241903Sdimvoid swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 408227825Stheraven 409227825Stheravennamespace this_thread 410227825Stheraven{ 411227825Stheraven 412262801Sdim_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& ns); 413227825Stheraven 414227825Stheraventemplate <class _Rep, class _Period> 415227825Stheravenvoid 416227825Stheravensleep_for(const chrono::duration<_Rep, _Period>& __d) 417227825Stheraven{ 418227825Stheraven using namespace chrono; 419241903Sdim if (__d > duration<_Rep, _Period>::zero()) 420241903Sdim { 421241903Sdim _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 422241903Sdim nanoseconds __ns; 423241903Sdim if (__d < _Max) 424241903Sdim { 425241903Sdim __ns = duration_cast<nanoseconds>(__d); 426241903Sdim if (__ns < __d) 427241903Sdim ++__ns; 428241903Sdim } 429241903Sdim else 430241903Sdim __ns = nanoseconds::max(); 431241903Sdim sleep_for(__ns); 432241903Sdim } 433227825Stheraven} 434227825Stheraven 435227825Stheraventemplate <class _Clock, class _Duration> 436227825Stheravenvoid 437227825Stheravensleep_until(const chrono::time_point<_Clock, _Duration>& __t) 438227825Stheraven{ 439227825Stheraven using namespace chrono; 440227825Stheraven mutex __mut; 441227825Stheraven condition_variable __cv; 442227825Stheraven unique_lock<mutex> __lk(__mut); 443227825Stheraven while (_Clock::now() < __t) 444227825Stheraven __cv.wait_until(__lk, __t); 445227825Stheraven} 446227825Stheraven 447227825Stheraventemplate <class _Duration> 448227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 449227825Stheravenvoid 450227825Stheravensleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 451227825Stheraven{ 452227825Stheraven using namespace chrono; 453227825Stheraven sleep_for(__t - steady_clock::now()); 454227825Stheraven} 455227825Stheraven 456227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 457241903Sdimvoid yield() _NOEXCEPT {sched_yield();} 458227825Stheraven 459227825Stheraven} // this_thread 460227825Stheraven 461227825Stheraven_LIBCPP_END_NAMESPACE_STD 462227825Stheraven 463278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS 464278724Sdim 465227825Stheraven#endif // _LIBCPP_THREAD 466