codekingpro/portable-devtools
115k
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCUDACXX_THREAD11#define _LIBCUDACXX_THREAD12 13/*14 15 thread synopsis16 17namespace std18{19 20class thread21{22public:23 class id;24 typedef pthread_t native_handle_type;25 26 thread() noexcept;27 template <class F, class ...Args> explicit thread(F&& f, Args&&... args);28 ~thread();29 30 thread(const thread&) = delete;31 thread(thread&& t) noexcept;32 33 thread& operator=(const thread&) = delete;34 thread& operator=(thread&& t) noexcept;35 36 void swap(thread& t) noexcept;37 38 bool joinable() const noexcept;39 void join();40 void detach();41 id get_id() const noexcept;42 native_handle_type native_handle();43 44 static unsigned hardware_concurrency() noexcept;45};46 47void swap(thread& x, thread& y) noexcept;48 49class thread::id50{51public:52 id() noexcept;53};54 55bool operator==(thread::id x, thread::id y) noexcept;56bool operator!=(thread::id x, thread::id y) noexcept;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;61 62template<class charT, class traits>63basic_ostream<charT, traits>&64operator<<(basic_ostream<charT, traits>& out, thread::id id);65 66namespace this_thread67{68 69thread::id get_id() noexcept;70 71void yield() noexcept;72 73template <class Clock, class Duration>74void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);75 76template <class Rep, class Period>77void sleep_for(const chrono::duration<Rep, Period>& rel_time);78 79} // this_thread80 81} // std82 83*/84 85#include <__config>86#include <iosfwd>87#include <__functional_base>88#include <type_traits>89#include <cstddef>90#include <functional>91#include <memory>92#include <system_error>93#include <chrono>94#include <__mutex_base>95#include <tuple>96#include <__threading_support>97#include <__debug>98 99#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)100# pragma GCC system_header101#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)102# pragma clang system_header103#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)104# pragma system_header105#endif // no system header106 107_LIBCUDACXX_PUSH_MACROS108#include <__undef_macros>109 110#ifdef _LIBCUDACXX_HAS_NO_THREADS111#error <thread> is not supported on this single threaded system112#else // !_LIBCUDACXX_HAS_NO_THREADS113 114_LIBCUDACXX_BEGIN_NAMESPACE_STD115 116template <class _Tp> class __thread_specific_ptr;117class _LIBCUDACXX_TYPE_VIS __thread_struct;118class _LIBCUDACXX_HIDDEN __thread_struct_imp;119class __assoc_sub_state;120 121_LIBCUDACXX_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();122 123class _LIBCUDACXX_TYPE_VIS __thread_struct124{125 __thread_struct_imp* __p_;126 127 __thread_struct(const __thread_struct&);128 __thread_struct& operator=(const __thread_struct&);129public:130 __thread_struct();131 ~__thread_struct();132 133 void notify_all_at_thread_exit(condition_variable*, mutex*);134 void __make_ready_at_thread_exit(__assoc_sub_state*);135};136 137template <class _Tp>138class __thread_specific_ptr139{140 __libcpp_tls_key __key_;141 142 // Only __thread_local_data() may construct a __thread_specific_ptr143 // and only with _Tp == __thread_struct.144 static_assert((is_same<_Tp, __thread_struct>::value), "");145 __thread_specific_ptr();146 friend _LIBCUDACXX_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data();147 148 __thread_specific_ptr(const __thread_specific_ptr&);149 __thread_specific_ptr& operator=(const __thread_specific_ptr&);150 151 _LIBCUDACXX_HIDDEN static void _LIBCUDACXX_TLS_DESTRUCTOR_CC __at_thread_exit(void*);152 153public:154 typedef _Tp* pointer;155 156 ~__thread_specific_ptr();157 158 _LIBCUDACXX_INLINE_VISIBILITY159 pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));}160 _LIBCUDACXX_INLINE_VISIBILITY161 pointer operator*() const {return *get();}162 _LIBCUDACXX_INLINE_VISIBILITY163 pointer operator->() const {return get();}164 void set_pointer(pointer __p);165};166 167template <class _Tp>168void _LIBCUDACXX_TLS_DESTRUCTOR_CC169__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p)170{171 delete static_cast<pointer>(__p);172}173 174template <class _Tp>175__thread_specific_ptr<_Tp>::__thread_specific_ptr()176{177 int __ec =178 __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit);179 if (__ec)180 __throw_system_error(__ec, "__thread_specific_ptr construction failed");181}182 183template <class _Tp>184__thread_specific_ptr<_Tp>::~__thread_specific_ptr()185{186 // __thread_specific_ptr is only created with a static storage duration187 // so this destructor is only invoked during program termination. Invoking188 // pthread_key_delete(__key_) may prevent other threads from deleting their189 // thread local data. For this reason we leak the key.190}191 192template <class _Tp>193void194__thread_specific_ptr<_Tp>::set_pointer(pointer __p)195{196 _LIBCUDACXX_ASSERT(get() == nullptr,197 "Attempting to overwrite thread local data");198 __libcpp_tls_set(__key_, __p);199}200 201template<>202struct _LIBCUDACXX_TEMPLATE_VIS hash<__thread_id>203 : public __unary_function<__thread_id, size_t>204{205 _LIBCUDACXX_INLINE_VISIBILITY206 size_t operator()(__thread_id __v) const noexcept207 {208 return hash<__libcpp_thread_id>()(__v.__id_);209 }210};211 212template<class _CharT, class _Traits>213_LIBCUDACXX_INLINE_VISIBILITY214basic_ostream<_CharT, _Traits>&215operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)216{return __os << __id.__id_;}217 218class _LIBCUDACXX_TYPE_VIS thread219{220 __libcpp_thread_t __t_;221 222 thread(const thread&);223 thread& operator=(const thread&);224public:225 typedef __thread_id id;226 typedef __libcpp_thread_t native_handle_type;227 228 _LIBCUDACXX_INLINE_VISIBILITY229 thread() noexcept : __t_(_LIBCUDACXX_NULL_THREAD) {}230 template <class _Fp, class ..._Args,231 class = typename enable_if232 <233 !is_same<__remove_cvref_t<_Fp>, thread>::value234 >::type235 >236 _LIBCUDACXX_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS237 explicit thread(_Fp&& __f, _Args&&... __args);238 ~thread();239 240 _LIBCUDACXX_INLINE_VISIBILITY241 thread(thread&& __t) noexcept : __t_(__t.__t_) {__t.__t_ = _LIBCUDACXX_NULL_THREAD;}242 _LIBCUDACXX_INLINE_VISIBILITY243 thread& operator=(thread&& __t) noexcept;244 245 _LIBCUDACXX_INLINE_VISIBILITY246 void swap(thread& __t) noexcept {_CUDA_VSTD::swap(__t_, __t.__t_);}247 248 _LIBCUDACXX_INLINE_VISIBILITY249 bool joinable() const noexcept {return !__libcpp_thread_isnull(&__t_);}250 void join();251 void detach();252 _LIBCUDACXX_INLINE_VISIBILITY253 id get_id() const noexcept {return __libcpp_thread_get_id(&__t_);}254 _LIBCUDACXX_INLINE_VISIBILITY255 native_handle_type native_handle() noexcept {return __t_;}256 257 static unsigned hardware_concurrency() noexcept;258};259 260template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices>261inline _LIBCUDACXX_INLINE_VISIBILITY262void263__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>)264{265 __invoke(_CUDA_VSTD::move(_CUDA_VSTD::get<1>(__t)), _CUDA_VSTD::move(_CUDA_VSTD::get<_Indices>(__t))...);266}267 268template <class _Fp>269void* __thread_proxy(void* __vp)270{271 // _Fp = std::tuple< unique_ptr<__thread_struct>, Functor, Args...>272 std::unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp));273 __thread_local_data().set_pointer(_CUDA_VSTD::get<0>(*__p).release());274 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index;275 __thread_execute(*__p, _Index());276 return nullptr;277}278 279template <class _Fp, class ..._Args,280 class281 >282thread::thread(_Fp&& __f, _Args&&... __args)283{284 typedef unique_ptr<__thread_struct> _TSPtr;285 _TSPtr __tsp(new __thread_struct);286 typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp;287 _CUDA_VSTD::unique_ptr<_Gp> __p(288 new _Gp(std::move(__tsp),289 __decay_copy(_CUDA_VSTD::forward<_Fp>(__f)),290 __decay_copy(_CUDA_VSTD::forward<_Args>(__args))...));291 int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());292 if (__ec == 0)293 __p.release();294 else295 __throw_system_error(__ec, "thread constructor failed");296}297 298inline299thread&300thread::operator=(thread&& __t) noexcept301{302 if (!__libcpp_thread_isnull(&__t_))303 terminate();304 __t_ = __t.__t_;305 __t.__t_ = _LIBCUDACXX_NULL_THREAD;306 return *this;307}308 309inline _LIBCUDACXX_INLINE_VISIBILITY310void swap(thread& __x, thread& __y) noexcept {__x.swap(__y);}311 312namespace this_thread313{314 315_LIBCUDACXX_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns);316 317template <class _Rep, class _Period>318void319sleep_for(const chrono::duration<_Rep, _Period>& __d)320{321 using namespace chrono;322 if (__d > duration<_Rep, _Period>::zero())323 {324#if defined(_LIBCUDACXX_COMPILER_GCC) && (__powerpc__ || __POWERPC__)325 // GCC's long double const folding is incomplete for IBM128 long doubles.326 constexpr duration<long double> _Max = nanoseconds::max();327#else328 constexpr duration<long double> _Max = duration<long double>(ULLONG_MAX/1000000000ULL) ;329#endif330 nanoseconds __ns;331 if (__d < _Max)332 {333 __ns = duration_cast<nanoseconds>(__d);334 if (__ns < __d)335 ++__ns;336 }337 else338 __ns = nanoseconds::max();339 sleep_for(__ns);340 }341}342 343template <class _Clock, class _Duration>344void345sleep_until(const chrono::time_point<_Clock, _Duration>& __t)346{347 using namespace chrono;348 mutex __mut;349 condition_variable __cv;350 unique_lock<mutex> __lk(__mut);351 while (_Clock::now() < __t)352 __cv.wait_until(__lk, __t);353}354 355template <class _Duration>356inline _LIBCUDACXX_INLINE_VISIBILITY357void358sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)359{360 using namespace chrono;361 sleep_for(__t - steady_clock::now());362}363 364inline _LIBCUDACXX_INLINE_VISIBILITY365void yield() noexcept {__libcpp_thread_yield();}366 367} // this_thread368 369_LIBCUDACXX_END_NAMESPACE_STD370 371#endif // !_LIBCUDACXX_HAS_NO_THREADS372 373_LIBCUDACXX_POP_MACROS374 375#endif // _LIBCUDACXX_THREAD376 