Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/std_thread.h
1 // std::thread declarations -*- C++ -*- 2 3 // Copyright (C) 2008-2025 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 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 #if __cplusplus >= 201103L 38 #include <bits/c++config.h> 39 40 #include <iosfwd> // std::basic_ostream 41 #include <tuple> // std::tuple 42 #include <bits/functional_hash.h> // std::hash 43 #include <bits/invoke.h> // std::__invoke 44 #include <bits/refwrap.h> // not required, but helpful to users 45 #include <bits/unique_ptr.h> // std::unique_ptr 46 47 #ifdef _GLIBCXX_HAS_GTHREADS 48 # include <bits/gthr.h> 49 #else 50 # include <errno.h> 51 # include <bits/functexcept.h> 52 #endif 53 54 namespace std _GLIBCXX_VISIBILITY(default) 55 { 56 _GLIBCXX_BEGIN_NAMESPACE_VERSION 57 58 #if __glibcxx_formatters 59 template<typename, typename> class formatter; 60 #endif 61 62 /** @addtogroup threads 63 * @{ 64 */ 65 66 /** A std::thread represents a new thread of execution. 67 * 68 * The default constructor creates an object that does not own a thread. 69 * The `thread(F&&, Args&&...)` constructor invokes a callable in a new 70 * thread, and owns that new thread. A `std::thread` that owns a thread 71 * is *joinable*. Joining a thread waits for it to finish executing, 72 * which happens when the callable running in that thread returns. 73 * 74 * A `std::thread` cannot be copied, but can be moved. Moving a joinable 75 * object transfers ownership of its thread to another object. 76 * 77 * A joinable `std::thread` must be explicitly joined (or detached) before 78 * it is destroyed or assigned to. Attempting to destroy a joinable thread 79 * will terminate the whole process. 80 * 81 * @headerfile thread 82 * @since C++11 83 */ 84 class thread 85 { 86 public: 87 #ifdef _GLIBCXX_HAS_GTHREADS 88 using native_handle_type = __gthread_t; 89 #else 90 using native_handle_type = int; 91 #endif 92 93 /** A std::thread::id is a unique identifier for a thread. 94 * 95 * @headerfile thread 96 * @since C++11 97 */ 98 class id 99 { 100 native_handle_type _M_thread; 101 102 public: 103 id() noexcept : _M_thread() { } 104 105 explicit 106 id(native_handle_type __id) : _M_thread(__id) { } 107 108 private: 109 friend class thread; 110 friend struct hash<id>; 111 112 friend bool 113 operator==(id __x, id __y) noexcept; 114 115 #if __cpp_lib_three_way_comparison 116 friend strong_ordering 117 operator<=>(id __x, id __y) noexcept; 118 #else 119 friend bool 120 operator<(id __x, id __y) noexcept; 121 #endif 122 123 template<class _CharT, class _Traits> 124 friend basic_ostream<_CharT, _Traits>& 125 operator<<(basic_ostream<_CharT, _Traits>& __out, id __id); 126 127 #if __glibcxx_formatters 128 friend formatter<id, char>; 129 friend formatter<id, wchar_t>; 130 #endif 131 }; 132 133 private: 134 id _M_id; 135 136 // _GLIBCXX_RESOLVE_LIB_DEFECTS 137 // 2097. packaged_task constructors should be constrained 138 // 3039. Unnecessary decay in thread and packaged_task 139 template<typename _Tp> 140 using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>; 141 142 public: 143 thread() noexcept = default; 144 145 #ifdef _GLIBCXX_HAS_GTHREADS 146 private: 147 // This adds to user code that creates std:thread objects (because 148 // it is called by the template ctor below) strong references to 149 // pthread_create and pthread_join, which ensures they are both 150 // linked in even during static linking. We can't depend on 151 // gthread calls to bring them in, because those may use weak 152 // references. 153 static void 154 _M_thread_deps_never_run() { 155 #ifdef GTHR_ACTIVE_PROXY 156 reinterpret_cast<void (*)(void)>(&pthread_create)(); 157 reinterpret_cast<void (*)(void)>(&pthread_join)(); 158 #endif 159 } 160 161 public: 162 template<typename _Callable, typename... _Args, 163 typename = _Require<__not_same<_Callable>>> 164 explicit 165 thread(_Callable&& __f, _Args&&... __args) 166 { 167 static_assert( __is_invocable<typename decay<_Callable>::type, 168 typename decay<_Args>::type...>::value, 169 "std::thread arguments must be invocable after conversion to rvalues" 170 ); 171 172 using _Wrapper = _Call_wrapper<_Callable, _Args...>; 173 // Create a call wrapper with DECAY_COPY(__f) as its target object 174 // and DECAY_COPY(__args)... as its bound argument entities. 175 _M_start_thread(_State_ptr(new _State_impl<_Wrapper>( 176 std::forward<_Callable>(__f), std::forward<_Args>(__args)...)), 177 _M_thread_deps_never_run); 178 } 179 #endif // _GLIBCXX_HAS_GTHREADS 180 181 ~thread() 182 { 183 if (joinable()) 184 std::__terminate(); 185 } 186 187 thread(const thread&) = delete; 188 189 thread(thread&& __t) noexcept 190 { swap(__t); } 191 192 thread& operator=(const thread&) = delete; 193 194 thread& operator=(thread&& __t) noexcept 195 { 196 if (joinable()) 197 std::__terminate(); 198 swap(__t); 199 return *this; 200 } 201 202 void 203 swap(thread& __t) noexcept 204 { std::swap(_M_id, __t._M_id); } 205 206 bool 207 joinable() const noexcept 208 { return !(_M_id == id()); } 209 210 void 211 join(); 212 213 void 214 detach(); 215 216 id 217 get_id() const noexcept 218 { return _M_id; } 219 220 /** @pre thread is joinable 221 */ 222 native_handle_type 223 native_handle() 224 { return _M_id._M_thread; } 225 226 // Returns a value that hints at the number of hardware thread contexts. 227 static unsigned int 228 hardware_concurrency() noexcept; 229 230 #ifdef _GLIBCXX_HAS_GTHREADS 231 #ifndef _GLIBCXX_THREAD_IMPL 232 private: 233 #endif 234 // Abstract base class for types that wrap arbitrary functors to be 235 // invoked in the new thread of execution. 236 struct _State 237 { 238 virtual ~_State(); 239 virtual void _M_run() = 0; 240 }; 241 using _State_ptr = unique_ptr<_State>; 242 243 private: 244 template<typename _Callable> 245 struct _State_impl : public _State 246 { 247 _Callable _M_func; 248 249 template<typename... _Args> 250 _State_impl(_Args&&... __args) 251 : _M_func(std::forward<_Args>(__args)...) 252 { } 253 254 void 255 _M_run() { _M_func(); } 256 }; 257 258 void 259 _M_start_thread(_State_ptr, void (*)()); 260 261 #if _GLIBCXX_THREAD_ABI_COMPAT 262 public: 263 struct _Impl_base; 264 typedef shared_ptr<_Impl_base> __shared_base_type; 265 struct _Impl_base 266 { 267 __shared_base_type _M_this_ptr; 268 virtual ~_Impl_base() = default; 269 virtual void _M_run() = 0; 270 }; 271 272 private: 273 void 274 _M_start_thread(__shared_base_type, void (*)()); 275 276 void 277 _M_start_thread(__shared_base_type); 278 #endif 279 280 private: 281 // A call wrapper that does INVOKE(forwarded tuple elements...) 282 template<typename _Tuple> 283 struct _Invoker 284 { 285 template<typename... _Args> 286 explicit 287 _Invoker(_Args&&... __args) 288 : _M_t(std::forward<_Args>(__args)...) 289 { } 290 291 _Tuple _M_t; 292 293 template<typename> 294 struct __result; 295 template<typename _Fn, typename... _Args> 296 struct __result<tuple<_Fn, _Args...>> 297 : __invoke_result<_Fn, _Args...> 298 { }; 299 300 template<size_t... _Ind> 301 typename __result<_Tuple>::type 302 _M_invoke(_Index_tuple<_Ind...>) 303 { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); } 304 305 typename __result<_Tuple>::type 306 operator()() 307 { 308 using _Indices 309 = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type; 310 return _M_invoke(_Indices()); 311 } 312 }; 313 314 public: 315 /// @cond undocumented 316 template<typename... _Tp> 317 using _Call_wrapper = _Invoker<tuple<typename decay<_Tp>::type...>>; 318 /// @endcond 319 #endif // _GLIBCXX_HAS_GTHREADS 320 }; 321 322 #ifndef _GLIBCXX_HAS_GTHREADS 323 inline void thread::join() { std::__throw_system_error(EINVAL); } 324 inline void thread::detach() { std::__throw_system_error(EINVAL); } 325 inline unsigned int thread::hardware_concurrency() noexcept { return 0; } 326 #endif 327 328 /// @relates std::thread 329 inline void 330 swap(thread& __x, thread& __y) noexcept 331 { __x.swap(__y); } 332 333 /// @relates std::thread::id 334 inline bool 335 operator==(thread::id __x, thread::id __y) noexcept 336 { 337 // pthread_equal is undefined if either thread ID is not valid, so we 338 // can't safely use __gthread_equal on default-constructed values (nor 339 // the non-zero value returned by this_thread::get_id() for 340 // single-threaded programs using GNU libc). Assume EqualityComparable. 341 return __x._M_thread == __y._M_thread; 342 } 343 344 // N.B. other comparison operators are defined in <thread> 345 346 // DR 889. 347 /// std::hash specialization for thread::id. 348 template<> 349 struct hash<thread::id> 350 : public __hash_base<size_t, thread::id> 351 { 352 size_t 353 operator()(const thread::id& __id) const noexcept 354 { return std::_Hash_impl::hash(__id._M_thread); } 355 }; 356 357 namespace this_thread 358 { 359 /// The unique identifier of the current thread. 360 inline thread::id 361 get_id() noexcept 362 { 363 #ifndef _GLIBCXX_HAS_GTHREADS 364 return thread::id(1); 365 #elif defined _GLIBCXX_NATIVE_THREAD_ID 366 return thread::id(_GLIBCXX_NATIVE_THREAD_ID); 367 #else 368 return thread::id(__gthread_self()); 369 #endif 370 } 371 372 /// Allow the implementation to schedule a different thread. 373 inline void 374 yield() noexcept 375 { 376 #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD 377 __gthread_yield(); 378 #endif 379 } 380 381 } // namespace this_thread 382 383 /// @} 384 385 _GLIBCXX_END_NAMESPACE_VERSION 386 } // namespace 387 #endif // C++11 388 389 #endif // _GLIBCXX_THREAD_H