libstdc++
std_thread.h
Go to the documentation of this file.
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>
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
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
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition: chrono.h:826
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition: invoke.h:92
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:138
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:72
ISO C++ entities toplevel namespace is std.
std::basic_ostream< _CharT, _Traits > & operator<<(std::basic_ostream< _CharT, _Traits > &__os, const bitset< _Nb > &__x)
Global I/O operators for bitsets.
Definition: bitset:1692
void yield() noexcept
Allow the implementation to schedule a different thread.
Definition: std_thread.h:374
thread::id get_id() noexcept
The unique identifier of the current thread.
Definition: std_thread.h:361
Template class basic_ostream.
Definition: ostream.h:67
Primary class template hash.
native_handle_type native_handle()
Definition: std_thread.h:223