110d565efSmrg// <thread> -*- C++ -*-
210d565efSmrg
3*ec02198aSmrg// Copyright (C) 2008-2020 Free Software Foundation, Inc.
410d565efSmrg//
510d565efSmrg// This file is part of the GNU ISO C++ Library.  This library is free
610d565efSmrg// software; you can redistribute it and/or modify it under the
710d565efSmrg// terms of the GNU General Public License as published by the
810d565efSmrg// Free Software Foundation; either version 3, or (at your option)
910d565efSmrg// any later version.
1010d565efSmrg
1110d565efSmrg// This library is distributed in the hope that it will be useful,
1210d565efSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
1310d565efSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1410d565efSmrg// GNU General Public License for more details.
1510d565efSmrg
1610d565efSmrg// Under Section 7 of GPL version 3, you are granted additional
1710d565efSmrg// permissions described in the GCC Runtime Library Exception, version
1810d565efSmrg// 3.1, as published by the Free Software Foundation.
1910d565efSmrg
2010d565efSmrg// You should have received a copy of the GNU General Public License and
2110d565efSmrg// a copy of the GCC Runtime Library Exception along with this program;
2210d565efSmrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2310d565efSmrg// <http://www.gnu.org/licenses/>.
2410d565efSmrg
2510d565efSmrg/** @file include/thread
2610d565efSmrg *  This is a Standard C++ Library header.
2710d565efSmrg */
2810d565efSmrg
2910d565efSmrg#ifndef _GLIBCXX_THREAD
3010d565efSmrg#define _GLIBCXX_THREAD 1
3110d565efSmrg
3210d565efSmrg#pragma GCC system_header
3310d565efSmrg
3410d565efSmrg#if __cplusplus < 201103L
3510d565efSmrg# include <bits/c++0x_warning.h>
3610d565efSmrg#else
3710d565efSmrg
38*ec02198aSmrg#include <bits/c++config.h>
3910d565efSmrg
400fc04c29Smrg#if defined(_GLIBCXX_HAS_GTHREADS)
41*ec02198aSmrg#include <bits/gthr.h>
42*ec02198aSmrg
43*ec02198aSmrg#include <chrono> // std::chrono::*
44*ec02198aSmrg#include <memory> // std::unique_ptr
45*ec02198aSmrg#include <tuple>  // std::tuple
46*ec02198aSmrg
47*ec02198aSmrg#if __cplusplus > 201703L
48*ec02198aSmrg# include <compare>	// std::strong_ordering
49*ec02198aSmrg# include <stop_token>	// std::stop_source, std::stop_token, std::nostopstate
50*ec02198aSmrg#endif
51*ec02198aSmrg
52*ec02198aSmrg#ifdef _GLIBCXX_USE_NANOSLEEP
53*ec02198aSmrg# include <cerrno>  // errno, EINTR
54*ec02198aSmrg# include <time.h>  // nanosleep
55*ec02198aSmrg#endif
56*ec02198aSmrg
57*ec02198aSmrg#include <bits/functional_hash.h> // std::hash
58*ec02198aSmrg#include <bits/invoke.h>	  // std::__invoke
5910d565efSmrg
6010d565efSmrgnamespace std _GLIBCXX_VISIBILITY(default)
6110d565efSmrg{
6210d565efSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
6310d565efSmrg
6410d565efSmrg  /**
6510d565efSmrg   * @defgroup threads Threads
6610d565efSmrg   * @ingroup concurrency
6710d565efSmrg   *
6810d565efSmrg   * Classes for thread support.
6910d565efSmrg   * @{
7010d565efSmrg   */
7110d565efSmrg
7210d565efSmrg  /// thread
7310d565efSmrg  class thread
7410d565efSmrg  {
7510d565efSmrg  public:
7610d565efSmrg    // Abstract base class for types that wrap arbitrary functors to be
7710d565efSmrg    // invoked in the new thread of execution.
7810d565efSmrg    struct _State
7910d565efSmrg    {
8010d565efSmrg      virtual ~_State();
8110d565efSmrg      virtual void _M_run() = 0;
8210d565efSmrg    };
8310d565efSmrg    using _State_ptr = unique_ptr<_State>;
8410d565efSmrg
8510d565efSmrg    typedef __gthread_t			native_handle_type;
8610d565efSmrg
8710d565efSmrg    /// thread::id
8810d565efSmrg    class id
8910d565efSmrg    {
9010d565efSmrg      native_handle_type	_M_thread;
9110d565efSmrg
9210d565efSmrg    public:
9310d565efSmrg      id() noexcept : _M_thread() { }
9410d565efSmrg
9510d565efSmrg      explicit
9610d565efSmrg      id(native_handle_type __id) : _M_thread(__id) { }
9710d565efSmrg
9810d565efSmrg    private:
9910d565efSmrg      friend class thread;
100*ec02198aSmrg      friend class hash<id>;
10110d565efSmrg
10210d565efSmrg      friend bool
103*ec02198aSmrg      operator==(id __x, id __y) noexcept;
10410d565efSmrg
105*ec02198aSmrg#if __cpp_lib_three_way_comparison
106*ec02198aSmrg      friend strong_ordering
107*ec02198aSmrg      operator<=>(id __x, id __y) noexcept;
108*ec02198aSmrg#else
10910d565efSmrg      friend bool
110*ec02198aSmrg      operator<(id __x, id __y) noexcept;
111*ec02198aSmrg#endif
11210d565efSmrg
11310d565efSmrg      template<class _CharT, class _Traits>
11410d565efSmrg	friend basic_ostream<_CharT, _Traits>&
115*ec02198aSmrg	operator<<(basic_ostream<_CharT, _Traits>& __out, id __id);
11610d565efSmrg    };
11710d565efSmrg
11810d565efSmrg  private:
11910d565efSmrg    id				_M_id;
12010d565efSmrg
12110d565efSmrg    // _GLIBCXX_RESOLVE_LIB_DEFECTS
12210d565efSmrg    // 2097.  packaged_task constructors should be constrained
1230fc04c29Smrg    // 3039. Unnecessary decay in thread and packaged_task
124c7a68eb7Smrg    template<typename _Tp>
1250fc04c29Smrg      using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>;
12610d565efSmrg
127c7a68eb7Smrg  public:
128c7a68eb7Smrg    thread() noexcept = default;
12910d565efSmrg
130c7a68eb7Smrg    template<typename _Callable, typename... _Args,
131c7a68eb7Smrg	     typename = _Require<__not_same<_Callable>>>
13210d565efSmrg      explicit
13310d565efSmrg      thread(_Callable&& __f, _Args&&... __args)
13410d565efSmrg      {
135c7a68eb7Smrg	static_assert( __is_invocable<typename decay<_Callable>::type,
136c7a68eb7Smrg				      typename decay<_Args>::type...>::value,
137c7a68eb7Smrg	  "std::thread arguments must be invocable after conversion to rvalues"
138c7a68eb7Smrg	  );
139c7a68eb7Smrg
14010d565efSmrg#ifdef GTHR_ACTIVE_PROXY
14110d565efSmrg	// Create a reference to pthread_create, not just the gthr weak symbol.
14210d565efSmrg	auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
14310d565efSmrg#else
14410d565efSmrg	auto __depend = nullptr;
14510d565efSmrg#endif
146*ec02198aSmrg	// A call wrapper holding tuple{DECAY_COPY(__f), DECAY_COPY(__args)...}
147*ec02198aSmrg	using _Invoker_type = _Invoker<__decayed_tuple<_Callable, _Args...>>;
148*ec02198aSmrg
149*ec02198aSmrg	_M_start_thread(_S_make_state<_Invoker_type>(
150*ec02198aSmrg	      std::forward<_Callable>(__f), std::forward<_Args>(__args)...),
15110d565efSmrg	    __depend);
15210d565efSmrg      }
15310d565efSmrg
15410d565efSmrg    ~thread()
15510d565efSmrg    {
15610d565efSmrg      if (joinable())
15710d565efSmrg	std::terminate();
15810d565efSmrg    }
15910d565efSmrg
160c7a68eb7Smrg    thread(const thread&) = delete;
161c7a68eb7Smrg
162c7a68eb7Smrg    thread(thread&& __t) noexcept
163c7a68eb7Smrg    { swap(__t); }
164c7a68eb7Smrg
16510d565efSmrg    thread& operator=(const thread&) = delete;
16610d565efSmrg
16710d565efSmrg    thread& operator=(thread&& __t) noexcept
16810d565efSmrg    {
16910d565efSmrg      if (joinable())
17010d565efSmrg	std::terminate();
17110d565efSmrg      swap(__t);
17210d565efSmrg      return *this;
17310d565efSmrg    }
17410d565efSmrg
17510d565efSmrg    void
17610d565efSmrg    swap(thread& __t) noexcept
17710d565efSmrg    { std::swap(_M_id, __t._M_id); }
17810d565efSmrg
17910d565efSmrg    bool
18010d565efSmrg    joinable() const noexcept
18110d565efSmrg    { return !(_M_id == id()); }
18210d565efSmrg
18310d565efSmrg    void
18410d565efSmrg    join();
18510d565efSmrg
18610d565efSmrg    void
18710d565efSmrg    detach();
18810d565efSmrg
189*ec02198aSmrg    id
19010d565efSmrg    get_id() const noexcept
19110d565efSmrg    { return _M_id; }
19210d565efSmrg
19310d565efSmrg    /** @pre thread is joinable
19410d565efSmrg     */
19510d565efSmrg    native_handle_type
19610d565efSmrg    native_handle()
19710d565efSmrg    { return _M_id._M_thread; }
19810d565efSmrg
19910d565efSmrg    // Returns a value that hints at the number of hardware thread contexts.
20010d565efSmrg    static unsigned int
20110d565efSmrg    hardware_concurrency() noexcept;
20210d565efSmrg
20310d565efSmrg  private:
20410d565efSmrg    template<typename _Callable>
20510d565efSmrg      struct _State_impl : public _State
20610d565efSmrg      {
20710d565efSmrg	_Callable		_M_func;
20810d565efSmrg
209*ec02198aSmrg	template<typename... _Args>
210*ec02198aSmrg	  _State_impl(_Args&&... __args)
211*ec02198aSmrg	  : _M_func{{std::forward<_Args>(__args)...}}
21210d565efSmrg	  { }
21310d565efSmrg
21410d565efSmrg	void
21510d565efSmrg	_M_run() { _M_func(); }
21610d565efSmrg      };
21710d565efSmrg
21810d565efSmrg    void
21910d565efSmrg    _M_start_thread(_State_ptr, void (*)());
22010d565efSmrg
221*ec02198aSmrg    template<typename _Callable, typename... _Args>
22210d565efSmrg      static _State_ptr
223*ec02198aSmrg      _S_make_state(_Args&&... __args)
22410d565efSmrg      {
22510d565efSmrg	using _Impl = _State_impl<_Callable>;
226*ec02198aSmrg	return _State_ptr{new _Impl{std::forward<_Args>(__args)...}};
22710d565efSmrg      }
22810d565efSmrg#if _GLIBCXX_THREAD_ABI_COMPAT
22910d565efSmrg  public:
23010d565efSmrg    struct _Impl_base;
23110d565efSmrg    typedef shared_ptr<_Impl_base>	__shared_base_type;
23210d565efSmrg    struct _Impl_base
23310d565efSmrg    {
23410d565efSmrg      __shared_base_type	_M_this_ptr;
23510d565efSmrg      virtual ~_Impl_base() = default;
23610d565efSmrg      virtual void _M_run() = 0;
23710d565efSmrg    };
23810d565efSmrg
23910d565efSmrg  private:
24010d565efSmrg    void
24110d565efSmrg    _M_start_thread(__shared_base_type, void (*)());
24210d565efSmrg
24310d565efSmrg    void
24410d565efSmrg    _M_start_thread(__shared_base_type);
24510d565efSmrg#endif
24610d565efSmrg
24710d565efSmrg  private:
24810d565efSmrg    // A call wrapper that does INVOKE(forwarded tuple elements...)
24910d565efSmrg    template<typename _Tuple>
25010d565efSmrg      struct _Invoker
25110d565efSmrg      {
25210d565efSmrg	_Tuple _M_t;
25310d565efSmrg
2540fc04c29Smrg	template<typename>
2550fc04c29Smrg	  struct __result;
2560fc04c29Smrg	template<typename _Fn, typename... _Args>
2570fc04c29Smrg	  struct __result<tuple<_Fn, _Args...>>
2580fc04c29Smrg	  : __invoke_result<_Fn, _Args...>
2590fc04c29Smrg	  { };
26010d565efSmrg
26110d565efSmrg	template<size_t... _Ind>
2620fc04c29Smrg	  typename __result<_Tuple>::type
26310d565efSmrg	  _M_invoke(_Index_tuple<_Ind...>)
26410d565efSmrg	  { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
26510d565efSmrg
2660fc04c29Smrg	typename __result<_Tuple>::type
2670fc04c29Smrg	operator()()
2680fc04c29Smrg	{
26910d565efSmrg	  using _Indices
27010d565efSmrg	    = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
2710fc04c29Smrg	  return _M_invoke(_Indices());
2720fc04c29Smrg	}
27310d565efSmrg      };
27410d565efSmrg
27510d565efSmrg    template<typename... _Tp>
2760fc04c29Smrg      using __decayed_tuple = tuple<typename decay<_Tp>::type...>;
27710d565efSmrg
27810d565efSmrg  public:
27910d565efSmrg    // Returns a call wrapper that stores
28010d565efSmrg    // tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}.
28110d565efSmrg    template<typename _Callable, typename... _Args>
28210d565efSmrg      static _Invoker<__decayed_tuple<_Callable, _Args...>>
28310d565efSmrg      __make_invoker(_Callable&& __callable, _Args&&... __args)
28410d565efSmrg      {
28510d565efSmrg	return { __decayed_tuple<_Callable, _Args...>{
28610d565efSmrg	    std::forward<_Callable>(__callable), std::forward<_Args>(__args)...
28710d565efSmrg	} };
28810d565efSmrg      }
28910d565efSmrg  };
29010d565efSmrg
29110d565efSmrg  inline void
29210d565efSmrg  swap(thread& __x, thread& __y) noexcept
29310d565efSmrg  { __x.swap(__y); }
29410d565efSmrg
29510d565efSmrg  inline bool
29610d565efSmrg  operator==(thread::id __x, thread::id __y) noexcept
29710d565efSmrg  {
29810d565efSmrg    // pthread_equal is undefined if either thread ID is not valid, so we
29910d565efSmrg    // can't safely use __gthread_equal on default-constructed values (nor
30010d565efSmrg    // the non-zero value returned by this_thread::get_id() for
30110d565efSmrg    // single-threaded programs using GNU libc). Assume EqualityComparable.
30210d565efSmrg    return __x._M_thread == __y._M_thread;
30310d565efSmrg  }
30410d565efSmrg
305*ec02198aSmrg#if __cpp_lib_three_way_comparison
306*ec02198aSmrg  inline strong_ordering
307*ec02198aSmrg  operator<=>(thread::id __x, thread::id __y) noexcept
308*ec02198aSmrg  { return __x._M_thread <=> __y._M_thread; }
309*ec02198aSmrg#else
31010d565efSmrg  inline bool
31110d565efSmrg  operator!=(thread::id __x, thread::id __y) noexcept
31210d565efSmrg  { return !(__x == __y); }
31310d565efSmrg
31410d565efSmrg  inline bool
31510d565efSmrg  operator<(thread::id __x, thread::id __y) noexcept
31610d565efSmrg  {
31710d565efSmrg    // Pthreads doesn't define any way to do this, so we just have to
31810d565efSmrg    // assume native_handle_type is LessThanComparable.
31910d565efSmrg    return __x._M_thread < __y._M_thread;
32010d565efSmrg  }
32110d565efSmrg
32210d565efSmrg  inline bool
32310d565efSmrg  operator<=(thread::id __x, thread::id __y) noexcept
32410d565efSmrg  { return !(__y < __x); }
32510d565efSmrg
32610d565efSmrg  inline bool
32710d565efSmrg  operator>(thread::id __x, thread::id __y) noexcept
32810d565efSmrg  { return __y < __x; }
32910d565efSmrg
33010d565efSmrg  inline bool
33110d565efSmrg  operator>=(thread::id __x, thread::id __y) noexcept
33210d565efSmrg  { return !(__x < __y); }
333*ec02198aSmrg#endif // __cpp_lib_three_way_comparison
33410d565efSmrg
33510d565efSmrg  // DR 889.
33610d565efSmrg  /// std::hash specialization for thread::id.
33710d565efSmrg  template<>
33810d565efSmrg    struct hash<thread::id>
33910d565efSmrg    : public __hash_base<size_t, thread::id>
34010d565efSmrg    {
34110d565efSmrg      size_t
34210d565efSmrg      operator()(const thread::id& __id) const noexcept
34310d565efSmrg      { return std::_Hash_impl::hash(__id._M_thread); }
34410d565efSmrg    };
34510d565efSmrg
34610d565efSmrg  template<class _CharT, class _Traits>
34710d565efSmrg    inline basic_ostream<_CharT, _Traits>&
34810d565efSmrg    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
34910d565efSmrg    {
35010d565efSmrg      if (__id == thread::id())
35110d565efSmrg	return __out << "thread::id of a non-executing thread";
35210d565efSmrg      else
35310d565efSmrg	return __out << __id._M_thread;
35410d565efSmrg    }
35510d565efSmrg
35610d565efSmrg  /** @namespace std::this_thread
357*ec02198aSmrg   *  @brief ISO C++ 2011 namespace for interacting with the current thread
358*ec02198aSmrg   *
359*ec02198aSmrg   *  C++11 30.3.2 [thread.thread.this] Namespace this_thread.
36010d565efSmrg   */
36110d565efSmrg  namespace this_thread
36210d565efSmrg  {
36310d565efSmrg    /// get_id
36410d565efSmrg    inline thread::id
36510d565efSmrg    get_id() noexcept
36610d565efSmrg    {
367*ec02198aSmrg#ifdef _GLIBCXX_NATIVE_THREAD_ID
368*ec02198aSmrg      return thread::id(_GLIBCXX_NATIVE_THREAD_ID);
369*ec02198aSmrg#else
37010d565efSmrg      return thread::id(__gthread_self());
371*ec02198aSmrg#endif
37210d565efSmrg    }
37310d565efSmrg
37410d565efSmrg    /// yield
37510d565efSmrg    inline void
37610d565efSmrg    yield() noexcept
37710d565efSmrg    {
37810d565efSmrg#ifdef _GLIBCXX_USE_SCHED_YIELD
37910d565efSmrg      __gthread_yield();
38010d565efSmrg#endif
38110d565efSmrg    }
38210d565efSmrg
38310d565efSmrg    void
38410d565efSmrg    __sleep_for(chrono::seconds, chrono::nanoseconds);
38510d565efSmrg
38610d565efSmrg    /// sleep_for
38710d565efSmrg    template<typename _Rep, typename _Period>
38810d565efSmrg      inline void
38910d565efSmrg      sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
39010d565efSmrg      {
39110d565efSmrg	if (__rtime <= __rtime.zero())
39210d565efSmrg	  return;
39310d565efSmrg	auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
39410d565efSmrg	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
39510d565efSmrg#ifdef _GLIBCXX_USE_NANOSLEEP
39610d565efSmrg	__gthread_time_t __ts =
39710d565efSmrg	  {
39810d565efSmrg	    static_cast<std::time_t>(__s.count()),
39910d565efSmrg	    static_cast<long>(__ns.count())
40010d565efSmrg	  };
40110d565efSmrg	while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
40210d565efSmrg	  { }
40310d565efSmrg#else
40410d565efSmrg	__sleep_for(__s, __ns);
40510d565efSmrg#endif
40610d565efSmrg      }
40710d565efSmrg
40810d565efSmrg    /// sleep_until
40910d565efSmrg    template<typename _Clock, typename _Duration>
41010d565efSmrg      inline void
41110d565efSmrg      sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
41210d565efSmrg      {
413*ec02198aSmrg#if __cplusplus > 201703L
414*ec02198aSmrg	static_assert(chrono::is_clock_v<_Clock>);
415*ec02198aSmrg#endif
41610d565efSmrg	auto __now = _Clock::now();
41710d565efSmrg	if (_Clock::is_steady)
41810d565efSmrg	  {
41910d565efSmrg	    if (__now < __atime)
42010d565efSmrg	      sleep_for(__atime - __now);
42110d565efSmrg	    return;
42210d565efSmrg	  }
42310d565efSmrg	while (__now < __atime)
42410d565efSmrg	  {
42510d565efSmrg	    sleep_for(__atime - __now);
42610d565efSmrg	    __now = _Clock::now();
42710d565efSmrg	  }
42810d565efSmrg      }
42910d565efSmrg  }
43010d565efSmrg
431*ec02198aSmrg  /// @} group threads
43210d565efSmrg
433*ec02198aSmrg#ifdef __cpp_lib_jthread
434*ec02198aSmrg
435*ec02198aSmrg  class jthread
436*ec02198aSmrg  {
437*ec02198aSmrg  public:
438*ec02198aSmrg    using id = thread::id;
439*ec02198aSmrg    using native_handle_type = thread::native_handle_type;
440*ec02198aSmrg
441*ec02198aSmrg    jthread() noexcept
442*ec02198aSmrg    : _M_stop_source{nostopstate}
443*ec02198aSmrg    { }
444*ec02198aSmrg
445*ec02198aSmrg    template<typename _Callable, typename... _Args,
446*ec02198aSmrg	     typename = enable_if_t<!is_same_v<remove_cvref_t<_Callable>,
447*ec02198aSmrg					       jthread>>>
448*ec02198aSmrg      explicit
449*ec02198aSmrg      jthread(_Callable&& __f, _Args&&... __args)
450*ec02198aSmrg      : _M_thread{_S_create(_M_stop_source, std::forward<_Callable>(__f),
451*ec02198aSmrg			    std::forward<_Args>(__args)...)}
452*ec02198aSmrg      { }
453*ec02198aSmrg
454*ec02198aSmrg    jthread(const jthread&) = delete;
455*ec02198aSmrg    jthread(jthread&&) noexcept = default;
456*ec02198aSmrg
457*ec02198aSmrg    ~jthread()
458*ec02198aSmrg    {
459*ec02198aSmrg      if (joinable())
460*ec02198aSmrg        {
461*ec02198aSmrg          request_stop();
462*ec02198aSmrg          join();
463*ec02198aSmrg        }
464*ec02198aSmrg    }
465*ec02198aSmrg
466*ec02198aSmrg    jthread&
467*ec02198aSmrg    operator=(const jthread&) = delete;
468*ec02198aSmrg
469*ec02198aSmrg    jthread&
470*ec02198aSmrg    operator=(jthread&& __other) noexcept
471*ec02198aSmrg    {
472*ec02198aSmrg      std::jthread(std::move(__other)).swap(*this);
473*ec02198aSmrg      return *this;
474*ec02198aSmrg    }
475*ec02198aSmrg
476*ec02198aSmrg    void
477*ec02198aSmrg    swap(jthread& __other) noexcept
478*ec02198aSmrg    {
479*ec02198aSmrg      std::swap(_M_stop_source, __other._M_stop_source);
480*ec02198aSmrg      std::swap(_M_thread, __other._M_thread);
481*ec02198aSmrg    }
482*ec02198aSmrg
483*ec02198aSmrg    [[nodiscard]] bool
484*ec02198aSmrg    joinable() const noexcept
485*ec02198aSmrg    {
486*ec02198aSmrg      return _M_thread.joinable();
487*ec02198aSmrg    }
488*ec02198aSmrg
489*ec02198aSmrg    void
490*ec02198aSmrg    join()
491*ec02198aSmrg    {
492*ec02198aSmrg      _M_thread.join();
493*ec02198aSmrg    }
494*ec02198aSmrg
495*ec02198aSmrg    void
496*ec02198aSmrg    detach()
497*ec02198aSmrg    {
498*ec02198aSmrg      _M_thread.detach();
499*ec02198aSmrg    }
500*ec02198aSmrg
501*ec02198aSmrg    [[nodiscard]] id
502*ec02198aSmrg    get_id() const noexcept
503*ec02198aSmrg    {
504*ec02198aSmrg      return _M_thread.get_id();
505*ec02198aSmrg    }
506*ec02198aSmrg
507*ec02198aSmrg    [[nodiscard]] native_handle_type
508*ec02198aSmrg    native_handle()
509*ec02198aSmrg    {
510*ec02198aSmrg      return _M_thread.native_handle();
511*ec02198aSmrg    }
512*ec02198aSmrg
513*ec02198aSmrg    [[nodiscard]] static unsigned
514*ec02198aSmrg    hardware_concurrency() noexcept
515*ec02198aSmrg    {
516*ec02198aSmrg      return thread::hardware_concurrency();
517*ec02198aSmrg    }
518*ec02198aSmrg
519*ec02198aSmrg    [[nodiscard]] stop_source
520*ec02198aSmrg    get_stop_source() noexcept
521*ec02198aSmrg    {
522*ec02198aSmrg      return _M_stop_source;
523*ec02198aSmrg    }
524*ec02198aSmrg
525*ec02198aSmrg    [[nodiscard]] stop_token
526*ec02198aSmrg    get_stop_token() const noexcept
527*ec02198aSmrg    {
528*ec02198aSmrg      return _M_stop_source.get_token();
529*ec02198aSmrg    }
530*ec02198aSmrg
531*ec02198aSmrg    bool request_stop() noexcept
532*ec02198aSmrg    {
533*ec02198aSmrg      return _M_stop_source.request_stop();
534*ec02198aSmrg    }
535*ec02198aSmrg
536*ec02198aSmrg    friend void swap(jthread& __lhs, jthread& __rhs) noexcept
537*ec02198aSmrg    {
538*ec02198aSmrg      __lhs.swap(__rhs);
539*ec02198aSmrg    }
540*ec02198aSmrg
541*ec02198aSmrg  private:
542*ec02198aSmrg    template<typename _Callable, typename... _Args>
543*ec02198aSmrg      static thread
544*ec02198aSmrg      _S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
545*ec02198aSmrg      {
546*ec02198aSmrg	if constexpr(is_invocable_v<decay_t<_Callable>, stop_token,
547*ec02198aSmrg				    decay_t<_Args>...>)
548*ec02198aSmrg	  return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
549*ec02198aSmrg			std::forward<_Args>(__args)...};
550*ec02198aSmrg	else
551*ec02198aSmrg	  {
552*ec02198aSmrg	    static_assert(is_invocable_v<decay_t<_Callable>,
553*ec02198aSmrg					 decay_t<_Args>...>,
554*ec02198aSmrg			  "std::thread arguments must be invocable after"
555*ec02198aSmrg			  " conversion to rvalues");
556*ec02198aSmrg	    return thread{std::forward<_Callable>(__f),
557*ec02198aSmrg			  std::forward<_Args>(__args)...};
558*ec02198aSmrg	  }
559*ec02198aSmrg      }
560*ec02198aSmrg
561*ec02198aSmrg    stop_source _M_stop_source;
562*ec02198aSmrg    thread _M_thread;
563*ec02198aSmrg  };
564*ec02198aSmrg#endif // __cpp_lib_jthread
565c7a68eb7Smrg_GLIBCXX_END_NAMESPACE_VERSION
56610d565efSmrg} // namespace
5670fc04c29Smrg#endif // _GLIBCXX_HAS_GTHREADS
56810d565efSmrg#endif // C++11
56910d565efSmrg#endif // _GLIBCXX_THREAD
570