1 // std::thread declarations -*- C++ -*-
3 // Copyright (C) 2008-2024 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
30 #ifndef _GLIBCXX_THREAD_H
31 #define _GLIBCXX_THREAD_H 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201103L
36 #include <bits/c++config.h>
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
45 #ifdef _GLIBCXX_HAS_GTHREADS
46 # include <bits/gthr.h>
49 # include <bits/functexcept.h>
52 namespace std
_GLIBCXX_VISIBILITY(default)
54 _GLIBCXX_BEGIN_NAMESPACE_VERSION
56 /** @addtogroup threads
60 /** A std::thread represents a new thread of execution.
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.
68 * A `std::thread` cannot be copied, but can be moved. Moving a joinable
69 * object transfers ownership of its thread to another object.
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.
81 #ifdef _GLIBCXX_HAS_GTHREADS
82 using native_handle_type
= __gthread_t
;
84 using native_handle_type
= int;
87 /** A std::thread::id is a unique identifier for a thread.
94 native_handle_type _M_thread
;
97 id() noexcept
: _M_thread() { }
100 id(native_handle_type __id
) : _M_thread(__id
) { }
104 friend struct hash
<id
>;
107 operator==(id __x
, id __y
) noexcept
;
109 #if __cpp_lib_three_way_comparison
110 friend strong_ordering
111 operator<=>(id __x
, id __y
) noexcept
;
114 operator<(id __x
, id __y
) noexcept
;
117 template<class _CharT
, class _Traits
>
118 friend basic_ostream
<_CharT
, _Traits
>&
119 operator<<(basic_ostream
<_CharT
, _Traits
>& __out
, id __id
);
125 // _GLIBCXX_RESOLVE_LIB_DEFECTS
126 // 2097. packaged_task constructors should be constrained
127 // 3039. Unnecessary decay in thread and packaged_task
128 template<typename _Tp
>
129 using __not_same
= __not_
<is_same
<__remove_cvref_t
<_Tp
>, thread
>>;
132 thread() noexcept
= default;
134 #ifdef _GLIBCXX_HAS_GTHREADS
136 // This adds to user code that creates std:thread objects (because
137 // it is called by the template ctor below) strong references to
138 // pthread_create and pthread_join, which ensures they are both
139 // linked in even during static linking. We can't depend on
140 // gthread calls to bring them in, because those may use weak
143 _M_thread_deps_never_run() {
144 #ifdef GTHR_ACTIVE_PROXY
145 reinterpret_cast<void (*)(void)>(&pthread_create
)();
146 reinterpret_cast<void (*)(void)>(&pthread_join
)();
151 template<typename _Callable
, typename
... _Args
,
152 typename
= _Require
<__not_same
<_Callable
>>>
154 thread(_Callable
&& __f
, _Args
&&... __args
)
156 static_assert( __is_invocable
<typename decay
<_Callable
>::type
,
157 typename decay
<_Args
>::type
...>::value
,
158 "std::thread arguments must be invocable after conversion to rvalues"
161 using _Wrapper
= _Call_wrapper
<_Callable
, _Args
...>;
162 // Create a call wrapper with DECAY_COPY(__f) as its target object
163 // and DECAY_COPY(__args)... as its bound argument entities.
164 _M_start_thread(_State_ptr(new _State_impl
<_Wrapper
>(
165 std::forward
<_Callable
>(__f
), std::forward
<_Args
>(__args
)...)),
166 _M_thread_deps_never_run
);
168 #endif // _GLIBCXX_HAS_GTHREADS
176 thread(const thread
&) = delete;
178 thread(thread
&& __t
) noexcept
181 thread
& operator=(const thread
&) = delete;
183 thread
& operator=(thread
&& __t
) noexcept
192 swap(thread
& __t
) noexcept
193 { std::swap(_M_id
, __t
._M_id
); }
196 joinable() const noexcept
197 { return !(_M_id
== id()); }
206 get_id() const noexcept
209 /** @pre thread is joinable
213 { return _M_id
._M_thread
; }
215 // Returns a value that hints at the number of hardware thread contexts.
217 hardware_concurrency() noexcept
;
219 #ifdef _GLIBCXX_HAS_GTHREADS
220 #ifndef _GLIBCXX_THREAD_IMPL
223 // Abstract base class for types that wrap arbitrary functors to be
224 // invoked in the new thread of execution.
228 virtual void _M_run() = 0;
230 using _State_ptr
= unique_ptr
<_State
>;
233 template<typename _Callable
>
234 struct _State_impl
: public _State
238 template<typename
... _Args
>
239 _State_impl(_Args
&&... __args
)
240 : _M_func(std::forward
<_Args
>(__args
)...)
244 _M_run() { _M_func(); }
248 _M_start_thread(_State_ptr
, void (*)());
250 #if _GLIBCXX_THREAD_ABI_COMPAT
253 typedef shared_ptr
<_Impl_base
> __shared_base_type
;
256 __shared_base_type _M_this_ptr
;
257 virtual ~_Impl_base() = default;
258 virtual void _M_run() = 0;
263 _M_start_thread(__shared_base_type
, void (*)());
266 _M_start_thread(__shared_base_type
);
270 // A call wrapper that does INVOKE(forwarded tuple elements...)
271 template<typename _Tuple
>
274 template<typename
... _Args
>
276 _Invoker(_Args
&&... __args
)
277 : _M_t(std::forward
<_Args
>(__args
)...)
284 template<typename _Fn
, typename
... _Args
>
285 struct __result
<tuple
<_Fn
, _Args
...>>
286 : __invoke_result
<_Fn
, _Args
...>
289 template<size_t... _Ind
>
290 typename __result
<_Tuple
>::type
291 _M_invoke(_Index_tuple
<_Ind
...>)
292 { return std::__invoke(std::get
<_Ind
>(std::move(_M_t
))...); }
294 typename __result
<_Tuple
>::type
298 = typename _Build_index_tuple
<tuple_size
<_Tuple
>::value
>::__type
;
299 return _M_invoke(_Indices());
304 /// @cond undocumented
305 template<typename
... _Tp
>
306 using _Call_wrapper
= _Invoker
<tuple
<typename decay
<_Tp
>::type
...>>;
308 #endif // _GLIBCXX_HAS_GTHREADS
311 #ifndef _GLIBCXX_HAS_GTHREADS
312 inline void thread::join() { std::__throw_system_error(EINVAL
); }
313 inline void thread::detach() { std::__throw_system_error(EINVAL
); }
314 inline unsigned int thread::hardware_concurrency() noexcept
{ return 0; }
317 /// @relates std::thread
319 swap(thread
& __x
, thread
& __y
) noexcept
322 /// @relates std::thread::id
324 operator==(thread::id __x
, thread::id __y
) noexcept
326 // pthread_equal is undefined if either thread ID is not valid, so we
327 // can't safely use __gthread_equal on default-constructed values (nor
328 // the non-zero value returned by this_thread::get_id() for
329 // single-threaded programs using GNU libc). Assume EqualityComparable.
330 return __x
._M_thread
== __y
._M_thread
;
333 // N.B. other comparison operators are defined in <thread>
336 /// std::hash specialization for thread::id.
338 struct hash
<thread::id
>
339 : public __hash_base
<size_t, thread::id
>
342 operator()(const thread::id
& __id
) const noexcept
343 { return std::_Hash_impl::hash(__id
._M_thread
); }
346 namespace this_thread
348 /// The unique identifier of the current thread.
352 #ifndef _GLIBCXX_HAS_GTHREADS
353 return thread::id(1);
354 #elif defined _GLIBCXX_NATIVE_THREAD_ID
355 return thread::id(_GLIBCXX_NATIVE_THREAD_ID
);
357 return thread::id(__gthread_self());
361 /// Allow the implementation to schedule a different thread.
365 #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD
370 } // namespace this_thread
374 _GLIBCXX_END_NAMESPACE_VERSION
378 #endif // _GLIBCXX_THREAD_H