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 203template<> 204struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> 205 : public unary_function<__thread_id, size_t> 206{ 207 _LIBCPP_INLINE_VISIBILITY 208 size_t operator()(__thread_id __v) const _NOEXCEPT 209 { 210 return hash<__libcpp_thread_id>()(__v.__id_); 211 } 212}; 213 214template<class _CharT, class _Traits> 215_LIBCPP_INLINE_VISIBILITY 216basic_ostream<_CharT, _Traits>& 217operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) 218{return __os << __id.__id_;} 219 220class _LIBCPP_TYPE_VIS thread 221{ 222 __libcpp_thread_t __t_; 223 224 thread(const thread&); 225 thread& operator=(const thread&); 226public: 227 typedef __thread_id id; 228 typedef __libcpp_thread_t native_handle_type; 229 230 _LIBCPP_INLINE_VISIBILITY 231 thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} 232#ifndef _LIBCPP_CXX03_LANG 233 template <class _Fp, class ..._Args, 234 class = typename enable_if 235 < 236 !is_same<typename __uncvref<_Fp>::type, thread>::value 237 >::type 238 > 239 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 240 explicit thread(_Fp&& __f, _Args&&... __args); 241#else // _LIBCPP_CXX03_LANG 242 template <class _Fp> 243 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 244 explicit thread(_Fp __f); 245#endif 246 ~thread(); 247 248#ifndef _LIBCPP_CXX03_LANG 249 _LIBCPP_INLINE_VISIBILITY 250 thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) {__t.__t_ = _LIBCPP_NULL_THREAD;} 251 _LIBCPP_INLINE_VISIBILITY 252 thread& operator=(thread&& __t) _NOEXCEPT; 253#endif // _LIBCPP_CXX03_LANG 254 255 _LIBCPP_INLINE_VISIBILITY 256 void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} 257 258 _LIBCPP_INLINE_VISIBILITY 259 bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} 260 void join(); 261 void detach(); 262 _LIBCPP_INLINE_VISIBILITY 263 id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} 264 _LIBCPP_INLINE_VISIBILITY 265 native_handle_type native_handle() _NOEXCEPT {return __t_;} 266 267 static unsigned hardware_concurrency() _NOEXCEPT; 268}; 269 270#ifndef _LIBCPP_CXX03_LANG 271 272template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> 273inline _LIBCPP_INLINE_VISIBILITY 274void 275__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) 276{ 277 __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); 278} 279 280template <class _Fp> 281void* __thread_proxy(void* __vp) 282{ 283 // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...> 284 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 285 __thread_local_data().set_pointer(_VSTD::get<0>(*__p).release()); 286 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; 287 __thread_execute(*__p, _Index()); 288 return nullptr; 289} 290 291template <class _Fp, class ..._Args, 292 class 293 > 294thread::thread(_Fp&& __f, _Args&&... __args) 295{ 296 typedef unique_ptr<__thread_struct> _TSPtr; 297 _TSPtr __tsp(new __thread_struct); 298 typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; 299 _VSTD::unique_ptr<_Gp> __p( 300 new _Gp(std::move(__tsp), 301 __decay_copy(_VSTD::forward<_Fp>(__f)), 302 __decay_copy(_VSTD::forward<_Args>(__args))...)); 303 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); 304 if (__ec == 0) 305 __p.release(); 306 else 307 __throw_system_error(__ec, "thread constructor failed"); 308} 309 310inline 311thread& 312thread::operator=(thread&& __t) _NOEXCEPT 313{ 314 if (!__libcpp_thread_isnull(&__t_)) 315 terminate(); 316 __t_ = __t.__t_; 317 __t.__t_ = _LIBCPP_NULL_THREAD; 318 return *this; 319} 320 321#else // _LIBCPP_CXX03_LANG 322 323template <class _Fp> 324struct __thread_invoke_pair { 325 // This type is used to pass memory for thread local storage and a functor 326 // to a newly created thread because std::pair doesn't work with 327 // std::unique_ptr in C++03. 328 __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} 329 unique_ptr<__thread_struct> __tsp_; 330 _Fp __fn_; 331}; 332 333template <class _Fp> 334void* __thread_proxy_cxx03(void* __vp) 335{ 336 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); 337 __thread_local_data().set_pointer(__p->__tsp_.release()); 338 (__p->__fn_)(); 339 return nullptr; 340} 341 342template <class _Fp> 343thread::thread(_Fp __f) 344{ 345 346 typedef __thread_invoke_pair<_Fp> _InvokePair; 347 typedef std::unique_ptr<_InvokePair> _PairPtr; 348 _PairPtr __pp(new _InvokePair(__f)); 349 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); 350 if (__ec == 0) 351 __pp.release(); 352 else 353 __throw_system_error(__ec, "thread constructor failed"); 354} 355 356#endif // _LIBCPP_CXX03_LANG 357 358inline _LIBCPP_INLINE_VISIBILITY 359void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} 360 361namespace this_thread 362{ 363 364_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); 365 366template <class _Rep, class _Period> 367void 368sleep_for(const chrono::duration<_Rep, _Period>& __d) 369{ 370 using namespace chrono; 371 if (__d > duration<_Rep, _Period>::zero()) 372 { 373#if defined(_LIBCPP_COMPILER_GCC) && (__powerpc__ || __POWERPC__) 374 // GCC's long double const folding is incomplete for IBM128 long doubles. 375 _LIBCPP_CONSTEXPR duration<long double> _Max = nanoseconds::max(); 376#else 377 _LIBCPP_CONSTEXPR duration<long double> _Max = duration<long double>(ULLONG_MAX/1000000000ULL) ; 378#endif 379 nanoseconds __ns; 380 if (__d < _Max) 381 { 382 __ns = duration_cast<nanoseconds>(__d); 383 if (__ns < __d) 384 ++__ns; 385 } 386 else 387 __ns = nanoseconds::max(); 388 sleep_for(__ns); 389 } 390} 391 392template <class _Clock, class _Duration> 393void 394sleep_until(const chrono::time_point<_Clock, _Duration>& __t) 395{ 396 using namespace chrono; 397 mutex __mut; 398 condition_variable __cv; 399 unique_lock<mutex> __lk(__mut); 400 while (_Clock::now() < __t) 401 __cv.wait_until(__lk, __t); 402} 403 404template <class _Duration> 405inline _LIBCPP_INLINE_VISIBILITY 406void 407sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) 408{ 409 using namespace chrono; 410 sleep_for(__t - steady_clock::now()); 411} 412 413inline _LIBCPP_INLINE_VISIBILITY 414void yield() _NOEXCEPT {__libcpp_thread_yield();} 415 416} // this_thread 417 418_LIBCPP_END_NAMESPACE_STD 419 420#endif // !_LIBCPP_HAS_NO_THREADS 421 422_LIBCPP_POP_MACROS 423 424#endif // _LIBCPP_THREAD 425