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