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