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