Line data Source code
1 : // std::thread declarations -*- C++ -*- 2 : 3 : // Copyright (C) 2008-2021 Free Software Foundation, Inc. 4 : // 5 : // This file is part of the GNU ISO C++ Library. This library is free 6 : // software; you can redistribute it and/or modify it under the 7 : // terms of the GNU General Public License as published by the 8 : // Free Software Foundation; either version 3, or (at your option) 9 : // any later version. 10 : 11 : // This library is distributed in the hope that it will be useful, 12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : // GNU General Public License for more details. 15 : 16 : // Under Section 7 of GPL version 3, you are granted additional 17 : // permissions described in the GCC Runtime Library Exception, version 18 : // 3.1, as published by the Free Software Foundation. 19 : 20 : // You should have received a copy of the GNU General Public License and 21 : // a copy of the GCC Runtime Library Exception along with this program; 22 : // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 : // <http://www.gnu.org/licenses/>. 24 : 25 : /** @file bits/std_thread.h 26 : * This is an internal header file, included by other library headers. 27 : * Do not attempt to use it directly. @headername{thread} 28 : */ 29 : 30 : #ifndef _GLIBCXX_THREAD_H 31 : #define _GLIBCXX_THREAD_H 1 32 : 33 : #pragma GCC system_header 34 : 35 : #if __cplusplus >= 201103L 36 : #include <bits/c++config.h> 37 : 38 : #include <exception> // std::terminate 39 : #include <iosfwd> // std::basic_ostream 40 : #include <tuple> // std::tuple 41 : #include <bits/functional_hash.h> // std::hash 42 : #include <bits/invoke.h> // std::__invoke 43 : #include <bits/refwrap.h> // not required, but helpful to users 44 : #include <bits/unique_ptr.h> // std::unique_ptr 45 : 46 : #ifdef _GLIBCXX_HAS_GTHREADS 47 : # include <bits/gthr.h> 48 : #else 49 : # include <errno.h> 50 : # include <bits/functexcept.h> 51 : #endif 52 : 53 : namespace std _GLIBCXX_VISIBILITY(default) 54 : { 55 : _GLIBCXX_BEGIN_NAMESPACE_VERSION 56 : 57 : /** @addtogroup threads 58 : * @{ 59 : */ 60 : 61 : /// thread 62 : class thread 63 : { 64 : public: 65 : #ifdef _GLIBCXX_HAS_GTHREADS 66 : // Abstract base class for types that wrap arbitrary functors to be 67 : // invoked in the new thread of execution. 68 : struct _State 69 : { 70 : virtual ~_State(); 71 : virtual void _M_run() = 0; 72 : }; 73 : using _State_ptr = unique_ptr<_State>; 74 : 75 : using native_handle_type = __gthread_t; 76 : #else 77 : using native_handle_type = int; 78 : #endif 79 : 80 : /// thread::id 81 : class id 82 : { 83 : native_handle_type _M_thread; 84 : 85 : public: 86 29417 : id() noexcept : _M_thread() { } 87 : 88 : explicit 89 1035 : id(native_handle_type __id) : _M_thread(__id) { } 90 : 91 : private: 92 : friend class thread; 93 : friend struct hash<id>; 94 : 95 : friend bool 96 : operator==(id __x, id __y) noexcept; 97 : 98 : #if __cpp_lib_three_way_comparison 99 : friend strong_ordering 100 : operator<=>(id __x, id __y) noexcept; 101 : #else 102 : friend bool 103 : operator<(id __x, id __y) noexcept; 104 : #endif 105 : 106 : template<class _CharT, class _Traits> 107 : friend basic_ostream<_CharT, _Traits>& 108 : operator<<(basic_ostream<_CharT, _Traits>& __out, id __id); 109 : }; 110 : 111 : private: 112 : id _M_id; 113 : 114 : // _GLIBCXX_RESOLVE_LIB_DEFECTS 115 : // 2097. packaged_task constructors should be constrained 116 : // 3039. Unnecessary decay in thread and packaged_task 117 : template<typename _Tp> 118 : using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>; 119 : 120 : public: 121 1603 : thread() noexcept = default; 122 : 123 : #ifdef _GLIBCXX_HAS_GTHREADS 124 : template<typename _Callable, typename... _Args, 125 : typename = _Require<__not_same<_Callable>>> 126 : explicit 127 1366 : thread(_Callable&& __f, _Args&&... __args) 128 1366 : { 129 : static_assert( __is_invocable<typename decay<_Callable>::type, 130 : typename decay<_Args>::type...>::value, 131 : "std::thread arguments must be invocable after conversion to rvalues" 132 : ); 133 : 134 : #ifdef GTHR_ACTIVE_PROXY 135 : // Create a reference to pthread_create, not just the gthr weak symbol. 136 : auto __depend = reinterpret_cast<void(*)()>(&pthread_create); 137 : #else 138 1366 : auto __depend = nullptr; 139 : #endif 140 : using _Wrapper = _Call_wrapper<_Callable, _Args...>; 141 : // Create a call wrapper with DECAY_COPY(__f) as its target object 142 : // and DECAY_COPY(__args)... as its bound argument entities. 143 1366 : _M_start_thread(_State_ptr(new _State_impl<_Wrapper>( 144 1366 : std::forward<_Callable>(__f), std::forward<_Args>(__args)...)), 145 : __depend); 146 1366 : } 147 : #endif // _GLIBCXX_HAS_GTHREADS 148 : 149 2930 : ~thread() 150 : { 151 2930 : if (joinable()) 152 0 : std::terminate(); 153 2930 : } 154 : 155 : thread(const thread&) = delete; 156 : 157 1 : thread(thread&& __t) noexcept 158 1 : { swap(__t); } 159 : 160 : thread& operator=(const thread&) = delete; 161 : 162 1326 : thread& operator=(thread&& __t) noexcept 163 : { 164 1326 : if (joinable()) 165 0 : std::terminate(); 166 1326 : swap(__t); 167 1326 : return *this; 168 : } 169 : 170 : void 171 1327 : swap(thread& __t) noexcept 172 1327 : { std::swap(_M_id, __t._M_id); } 173 : 174 : bool 175 25033 : joinable() const noexcept 176 25033 : { return !(_M_id == id()); } 177 : 178 : void 179 : join(); 180 : 181 : void 182 : detach(); 183 : 184 : id 185 1035 : get_id() const noexcept 186 1035 : { return _M_id; } 187 : 188 : /** @pre thread is joinable 189 : */ 190 : native_handle_type 191 : native_handle() 192 : { return _M_id._M_thread; } 193 : 194 : // Returns a value that hints at the number of hardware thread contexts. 195 : static unsigned int 196 : hardware_concurrency() noexcept; 197 : 198 : #ifdef _GLIBCXX_HAS_GTHREADS 199 : private: 200 : template<typename _Callable> 201 : struct _State_impl : public _State 202 : { 203 : _Callable _M_func; 204 : 205 : template<typename... _Args> 206 1366 : _State_impl(_Args&&... __args) 207 1366 : : _M_func(std::forward<_Args>(__args)...) 208 1366 : { } 209 : 210 : void 211 1366 : _M_run() { _M_func(); } 212 : }; 213 : 214 : void 215 : _M_start_thread(_State_ptr, void (*)()); 216 : 217 : #if _GLIBCXX_THREAD_ABI_COMPAT 218 : public: 219 : struct _Impl_base; 220 : typedef shared_ptr<_Impl_base> __shared_base_type; 221 : struct _Impl_base 222 : { 223 : __shared_base_type _M_this_ptr; 224 : virtual ~_Impl_base() = default; 225 : virtual void _M_run() = 0; 226 : }; 227 : 228 : private: 229 : void 230 : _M_start_thread(__shared_base_type, void (*)()); 231 : 232 : void 233 : _M_start_thread(__shared_base_type); 234 : #endif 235 : 236 : private: 237 : // A call wrapper that does INVOKE(forwarded tuple elements...) 238 : template<typename _Tuple> 239 : struct _Invoker 240 : { 241 : template<typename... _Args> 242 : explicit 243 1366 : _Invoker(_Args&&... __args) 244 1366 : : _M_t(std::forward<_Args>(__args)...) 245 1366 : { } 246 : 247 : _Tuple _M_t; 248 : 249 : template<typename> 250 : struct __result; 251 : template<typename _Fn, typename... _Args> 252 : struct __result<tuple<_Fn, _Args...>> 253 : : __invoke_result<_Fn, _Args...> 254 : { }; 255 : 256 : template<size_t... _Ind> 257 : typename __result<_Tuple>::type 258 1366 : _M_invoke(_Index_tuple<_Ind...>) 259 1366 : { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); } 260 : 261 : typename __result<_Tuple>::type 262 1366 : operator()() 263 : { 264 : using _Indices 265 : = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type; 266 1366 : return _M_invoke(_Indices()); 267 : } 268 : }; 269 : 270 : public: 271 : template<typename... _Tp> 272 : using _Call_wrapper = _Invoker<tuple<typename decay<_Tp>::type...>>; 273 : #endif // _GLIBCXX_HAS_GTHREADS 274 : }; 275 : 276 : #ifndef _GLIBCXX_HAS_GTHREADS 277 : inline void thread::join() { std::__throw_system_error(EINVAL); } 278 : inline void thread::detach() { std::__throw_system_error(EINVAL); } 279 : inline unsigned int thread::hardware_concurrency() noexcept { return 0; } 280 : #endif 281 : 282 : inline void 283 : swap(thread& __x, thread& __y) noexcept 284 : { __x.swap(__y); } 285 : 286 : inline bool 287 25073 : operator==(thread::id __x, thread::id __y) noexcept 288 : { 289 : // pthread_equal is undefined if either thread ID is not valid, so we 290 : // can't safely use __gthread_equal on default-constructed values (nor 291 : // the non-zero value returned by this_thread::get_id() for 292 : // single-threaded programs using GNU libc). Assume EqualityComparable. 293 25073 : return __x._M_thread == __y._M_thread; 294 : } 295 : 296 : // N.B. other comparison operators are defined in <thread> 297 : 298 : // DR 889. 299 : /// std::hash specialization for thread::id. 300 : template<> 301 : struct hash<thread::id> 302 : : public __hash_base<size_t, thread::id> 303 : { 304 : size_t 305 : operator()(const thread::id& __id) const noexcept 306 : { return std::_Hash_impl::hash(__id._M_thread); } 307 : }; 308 : 309 : namespace this_thread 310 : { 311 : /// this_thread::get_id 312 : inline thread::id 313 1035 : get_id() noexcept 314 : { 315 : #ifndef _GLIBCXX_HAS_GTHREADS 316 : return thread::id(1); 317 : #elif defined _GLIBCXX_NATIVE_THREAD_ID 318 1035 : return thread::id(_GLIBCXX_NATIVE_THREAD_ID); 319 : #else 320 : return thread::id(__gthread_self()); 321 : #endif 322 : } 323 : 324 : /// this_thread::yield 325 : inline void 326 : yield() noexcept 327 : { 328 : #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD 329 : __gthread_yield(); 330 : #endif 331 : } 332 : 333 : } // namespace this_thread 334 : 335 : /// @} 336 : 337 : _GLIBCXX_END_NAMESPACE_VERSION 338 : } // namespace 339 : #endif // C++11 340 : 341 : #endif // _GLIBCXX_THREAD_H