xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/std/thread (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg// <thread> -*- C++ -*-
21debfc3dSmrg
3*8feb0f0bSmrg// Copyright (C) 2008-2020 Free Software Foundation, Inc.
41debfc3dSmrg//
51debfc3dSmrg// This file is part of the GNU ISO C++ Library.  This library is free
61debfc3dSmrg// software; you can redistribute it and/or modify it under the
71debfc3dSmrg// terms of the GNU General Public License as published by the
81debfc3dSmrg// Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg// any later version.
101debfc3dSmrg
111debfc3dSmrg// This library is distributed in the hope that it will be useful,
121debfc3dSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141debfc3dSmrg// GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg// Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg// permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg// 3.1, as published by the Free Software Foundation.
191debfc3dSmrg
201debfc3dSmrg// You should have received a copy of the GNU General Public License and
211debfc3dSmrg// a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
231debfc3dSmrg// <http://www.gnu.org/licenses/>.
241debfc3dSmrg
251debfc3dSmrg/** @file include/thread
261debfc3dSmrg *  This is a Standard C++ Library header.
271debfc3dSmrg */
281debfc3dSmrg
291debfc3dSmrg#ifndef _GLIBCXX_THREAD
301debfc3dSmrg#define _GLIBCXX_THREAD 1
311debfc3dSmrg
321debfc3dSmrg#pragma GCC system_header
331debfc3dSmrg
341debfc3dSmrg#if __cplusplus < 201103L
351debfc3dSmrg# include <bits/c++0x_warning.h>
361debfc3dSmrg#else
371debfc3dSmrg
38*8feb0f0bSmrg#include <bits/c++config.h>
391debfc3dSmrg
40c0a68be4Smrg#if defined(_GLIBCXX_HAS_GTHREADS)
41*8feb0f0bSmrg#include <bits/gthr.h>
42*8feb0f0bSmrg
43*8feb0f0bSmrg#include <chrono> // std::chrono::*
44*8feb0f0bSmrg#include <memory> // std::unique_ptr
45*8feb0f0bSmrg#include <tuple>  // std::tuple
46*8feb0f0bSmrg
47*8feb0f0bSmrg#if __cplusplus > 201703L
48*8feb0f0bSmrg# include <compare>	// std::strong_ordering
49*8feb0f0bSmrg# include <stop_token>	// std::stop_source, std::stop_token, std::nostopstate
50*8feb0f0bSmrg#endif
51*8feb0f0bSmrg
52*8feb0f0bSmrg#ifdef _GLIBCXX_USE_NANOSLEEP
53*8feb0f0bSmrg# include <cerrno>  // errno, EINTR
54*8feb0f0bSmrg# include <time.h>  // nanosleep
55*8feb0f0bSmrg#endif
56*8feb0f0bSmrg
57*8feb0f0bSmrg#include <bits/functional_hash.h> // std::hash
58*8feb0f0bSmrg#include <bits/invoke.h>	  // std::__invoke
591debfc3dSmrg
601debfc3dSmrgnamespace std _GLIBCXX_VISIBILITY(default)
611debfc3dSmrg{
621debfc3dSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
631debfc3dSmrg
641debfc3dSmrg  /**
651debfc3dSmrg   * @defgroup threads Threads
661debfc3dSmrg   * @ingroup concurrency
671debfc3dSmrg   *
681debfc3dSmrg   * Classes for thread support.
691debfc3dSmrg   * @{
701debfc3dSmrg   */
711debfc3dSmrg
721debfc3dSmrg  /// thread
731debfc3dSmrg  class thread
741debfc3dSmrg  {
751debfc3dSmrg  public:
761debfc3dSmrg    // Abstract base class for types that wrap arbitrary functors to be
771debfc3dSmrg    // invoked in the new thread of execution.
781debfc3dSmrg    struct _State
791debfc3dSmrg    {
801debfc3dSmrg      virtual ~_State();
811debfc3dSmrg      virtual void _M_run() = 0;
821debfc3dSmrg    };
831debfc3dSmrg    using _State_ptr = unique_ptr<_State>;
841debfc3dSmrg
851debfc3dSmrg    typedef __gthread_t			native_handle_type;
861debfc3dSmrg
871debfc3dSmrg    /// thread::id
881debfc3dSmrg    class id
891debfc3dSmrg    {
901debfc3dSmrg      native_handle_type	_M_thread;
911debfc3dSmrg
921debfc3dSmrg    public:
931debfc3dSmrg      id() noexcept : _M_thread() { }
941debfc3dSmrg
951debfc3dSmrg      explicit
961debfc3dSmrg      id(native_handle_type __id) : _M_thread(__id) { }
971debfc3dSmrg
981debfc3dSmrg    private:
991debfc3dSmrg      friend class thread;
100*8feb0f0bSmrg      friend class hash<id>;
1011debfc3dSmrg
1021debfc3dSmrg      friend bool
103*8feb0f0bSmrg      operator==(id __x, id __y) noexcept;
1041debfc3dSmrg
105*8feb0f0bSmrg#if __cpp_lib_three_way_comparison
106*8feb0f0bSmrg      friend strong_ordering
107*8feb0f0bSmrg      operator<=>(id __x, id __y) noexcept;
108*8feb0f0bSmrg#else
1091debfc3dSmrg      friend bool
110*8feb0f0bSmrg      operator<(id __x, id __y) noexcept;
111*8feb0f0bSmrg#endif
1121debfc3dSmrg
1131debfc3dSmrg      template<class _CharT, class _Traits>
1141debfc3dSmrg	friend basic_ostream<_CharT, _Traits>&
115*8feb0f0bSmrg	operator<<(basic_ostream<_CharT, _Traits>& __out, id __id);
1161debfc3dSmrg    };
1171debfc3dSmrg
1181debfc3dSmrg  private:
1191debfc3dSmrg    id				_M_id;
1201debfc3dSmrg
1211debfc3dSmrg    // _GLIBCXX_RESOLVE_LIB_DEFECTS
1221debfc3dSmrg    // 2097.  packaged_task constructors should be constrained
123c0a68be4Smrg    // 3039. Unnecessary decay in thread and packaged_task
124a2dc1f3fSmrg    template<typename _Tp>
125c0a68be4Smrg      using __not_same = __not_<is_same<__remove_cvref_t<_Tp>, thread>>;
1261debfc3dSmrg
127a2dc1f3fSmrg  public:
128a2dc1f3fSmrg    thread() noexcept = default;
1291debfc3dSmrg
130a2dc1f3fSmrg    template<typename _Callable, typename... _Args,
131a2dc1f3fSmrg	     typename = _Require<__not_same<_Callable>>>
1321debfc3dSmrg      explicit
1331debfc3dSmrg      thread(_Callable&& __f, _Args&&... __args)
1341debfc3dSmrg      {
135a2dc1f3fSmrg	static_assert( __is_invocable<typename decay<_Callable>::type,
136a2dc1f3fSmrg				      typename decay<_Args>::type...>::value,
137a2dc1f3fSmrg	  "std::thread arguments must be invocable after conversion to rvalues"
138a2dc1f3fSmrg	  );
139a2dc1f3fSmrg
1401debfc3dSmrg#ifdef GTHR_ACTIVE_PROXY
1411debfc3dSmrg	// Create a reference to pthread_create, not just the gthr weak symbol.
1421debfc3dSmrg	auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
1431debfc3dSmrg#else
1441debfc3dSmrg	auto __depend = nullptr;
1451debfc3dSmrg#endif
146*8feb0f0bSmrg	// A call wrapper holding tuple{DECAY_COPY(__f), DECAY_COPY(__args)...}
147*8feb0f0bSmrg	using _Invoker_type = _Invoker<__decayed_tuple<_Callable, _Args...>>;
148*8feb0f0bSmrg
149*8feb0f0bSmrg	_M_start_thread(_S_make_state<_Invoker_type>(
150*8feb0f0bSmrg	      std::forward<_Callable>(__f), std::forward<_Args>(__args)...),
1511debfc3dSmrg	    __depend);
1521debfc3dSmrg      }
1531debfc3dSmrg
1541debfc3dSmrg    ~thread()
1551debfc3dSmrg    {
1561debfc3dSmrg      if (joinable())
1571debfc3dSmrg	std::terminate();
1581debfc3dSmrg    }
1591debfc3dSmrg
160a2dc1f3fSmrg    thread(const thread&) = delete;
161a2dc1f3fSmrg
162a2dc1f3fSmrg    thread(thread&& __t) noexcept
163a2dc1f3fSmrg    { swap(__t); }
164a2dc1f3fSmrg
1651debfc3dSmrg    thread& operator=(const thread&) = delete;
1661debfc3dSmrg
1671debfc3dSmrg    thread& operator=(thread&& __t) noexcept
1681debfc3dSmrg    {
1691debfc3dSmrg      if (joinable())
1701debfc3dSmrg	std::terminate();
1711debfc3dSmrg      swap(__t);
1721debfc3dSmrg      return *this;
1731debfc3dSmrg    }
1741debfc3dSmrg
1751debfc3dSmrg    void
1761debfc3dSmrg    swap(thread& __t) noexcept
1771debfc3dSmrg    { std::swap(_M_id, __t._M_id); }
1781debfc3dSmrg
1791debfc3dSmrg    bool
1801debfc3dSmrg    joinable() const noexcept
1811debfc3dSmrg    { return !(_M_id == id()); }
1821debfc3dSmrg
1831debfc3dSmrg    void
1841debfc3dSmrg    join();
1851debfc3dSmrg
1861debfc3dSmrg    void
1871debfc3dSmrg    detach();
1881debfc3dSmrg
189*8feb0f0bSmrg    id
1901debfc3dSmrg    get_id() const noexcept
1911debfc3dSmrg    { return _M_id; }
1921debfc3dSmrg
1931debfc3dSmrg    /** @pre thread is joinable
1941debfc3dSmrg     */
1951debfc3dSmrg    native_handle_type
1961debfc3dSmrg    native_handle()
1971debfc3dSmrg    { return _M_id._M_thread; }
1981debfc3dSmrg
1991debfc3dSmrg    // Returns a value that hints at the number of hardware thread contexts.
2001debfc3dSmrg    static unsigned int
2011debfc3dSmrg    hardware_concurrency() noexcept;
2021debfc3dSmrg
2031debfc3dSmrg  private:
2041debfc3dSmrg    template<typename _Callable>
2051debfc3dSmrg      struct _State_impl : public _State
2061debfc3dSmrg      {
2071debfc3dSmrg	_Callable		_M_func;
2081debfc3dSmrg
209*8feb0f0bSmrg	template<typename... _Args>
210*8feb0f0bSmrg	  _State_impl(_Args&&... __args)
211*8feb0f0bSmrg	  : _M_func{{std::forward<_Args>(__args)...}}
2121debfc3dSmrg	  { }
2131debfc3dSmrg
2141debfc3dSmrg	void
2151debfc3dSmrg	_M_run() { _M_func(); }
2161debfc3dSmrg      };
2171debfc3dSmrg
2181debfc3dSmrg    void
2191debfc3dSmrg    _M_start_thread(_State_ptr, void (*)());
2201debfc3dSmrg
221*8feb0f0bSmrg    template<typename _Callable, typename... _Args>
2221debfc3dSmrg      static _State_ptr
223*8feb0f0bSmrg      _S_make_state(_Args&&... __args)
2241debfc3dSmrg      {
2251debfc3dSmrg	using _Impl = _State_impl<_Callable>;
226*8feb0f0bSmrg	return _State_ptr{new _Impl{std::forward<_Args>(__args)...}};
2271debfc3dSmrg      }
2281debfc3dSmrg#if _GLIBCXX_THREAD_ABI_COMPAT
2291debfc3dSmrg  public:
2301debfc3dSmrg    struct _Impl_base;
2311debfc3dSmrg    typedef shared_ptr<_Impl_base>	__shared_base_type;
2321debfc3dSmrg    struct _Impl_base
2331debfc3dSmrg    {
2341debfc3dSmrg      __shared_base_type	_M_this_ptr;
2351debfc3dSmrg      virtual ~_Impl_base() = default;
2361debfc3dSmrg      virtual void _M_run() = 0;
2371debfc3dSmrg    };
2381debfc3dSmrg
2391debfc3dSmrg  private:
2401debfc3dSmrg    void
2411debfc3dSmrg    _M_start_thread(__shared_base_type, void (*)());
2421debfc3dSmrg
2431debfc3dSmrg    void
2441debfc3dSmrg    _M_start_thread(__shared_base_type);
2451debfc3dSmrg#endif
2461debfc3dSmrg
2471debfc3dSmrg  private:
2481debfc3dSmrg    // A call wrapper that does INVOKE(forwarded tuple elements...)
2491debfc3dSmrg    template<typename _Tuple>
2501debfc3dSmrg      struct _Invoker
2511debfc3dSmrg      {
2521debfc3dSmrg	_Tuple _M_t;
2531debfc3dSmrg
254c0a68be4Smrg	template<typename>
255c0a68be4Smrg	  struct __result;
256c0a68be4Smrg	template<typename _Fn, typename... _Args>
257c0a68be4Smrg	  struct __result<tuple<_Fn, _Args...>>
258c0a68be4Smrg	  : __invoke_result<_Fn, _Args...>
259c0a68be4Smrg	  { };
2601debfc3dSmrg
2611debfc3dSmrg	template<size_t... _Ind>
262c0a68be4Smrg	  typename __result<_Tuple>::type
2631debfc3dSmrg	  _M_invoke(_Index_tuple<_Ind...>)
2641debfc3dSmrg	  { return std::__invoke(std::get<_Ind>(std::move(_M_t))...); }
2651debfc3dSmrg
266c0a68be4Smrg	typename __result<_Tuple>::type
267c0a68be4Smrg	operator()()
268c0a68be4Smrg	{
2691debfc3dSmrg	  using _Indices
2701debfc3dSmrg	    = typename _Build_index_tuple<tuple_size<_Tuple>::value>::__type;
271c0a68be4Smrg	  return _M_invoke(_Indices());
272c0a68be4Smrg	}
2731debfc3dSmrg      };
2741debfc3dSmrg
2751debfc3dSmrg    template<typename... _Tp>
276c0a68be4Smrg      using __decayed_tuple = tuple<typename decay<_Tp>::type...>;
2771debfc3dSmrg
2781debfc3dSmrg  public:
2791debfc3dSmrg    // Returns a call wrapper that stores
2801debfc3dSmrg    // tuple{DECAY_COPY(__callable), DECAY_COPY(__args)...}.
2811debfc3dSmrg    template<typename _Callable, typename... _Args>
2821debfc3dSmrg      static _Invoker<__decayed_tuple<_Callable, _Args...>>
2831debfc3dSmrg      __make_invoker(_Callable&& __callable, _Args&&... __args)
2841debfc3dSmrg      {
2851debfc3dSmrg	return { __decayed_tuple<_Callable, _Args...>{
2861debfc3dSmrg	    std::forward<_Callable>(__callable), std::forward<_Args>(__args)...
2871debfc3dSmrg	} };
2881debfc3dSmrg      }
2891debfc3dSmrg  };
2901debfc3dSmrg
2911debfc3dSmrg  inline void
2921debfc3dSmrg  swap(thread& __x, thread& __y) noexcept
2931debfc3dSmrg  { __x.swap(__y); }
2941debfc3dSmrg
2951debfc3dSmrg  inline bool
2961debfc3dSmrg  operator==(thread::id __x, thread::id __y) noexcept
2971debfc3dSmrg  {
2981debfc3dSmrg    // pthread_equal is undefined if either thread ID is not valid, so we
2991debfc3dSmrg    // can't safely use __gthread_equal on default-constructed values (nor
3001debfc3dSmrg    // the non-zero value returned by this_thread::get_id() for
3011debfc3dSmrg    // single-threaded programs using GNU libc). Assume EqualityComparable.
3021debfc3dSmrg    return __x._M_thread == __y._M_thread;
3031debfc3dSmrg  }
3041debfc3dSmrg
305*8feb0f0bSmrg#if __cpp_lib_three_way_comparison
306*8feb0f0bSmrg  inline strong_ordering
307*8feb0f0bSmrg  operator<=>(thread::id __x, thread::id __y) noexcept
308*8feb0f0bSmrg  { return __x._M_thread <=> __y._M_thread; }
309*8feb0f0bSmrg#else
3101debfc3dSmrg  inline bool
3111debfc3dSmrg  operator!=(thread::id __x, thread::id __y) noexcept
3121debfc3dSmrg  { return !(__x == __y); }
3131debfc3dSmrg
3141debfc3dSmrg  inline bool
3151debfc3dSmrg  operator<(thread::id __x, thread::id __y) noexcept
3161debfc3dSmrg  {
3171debfc3dSmrg    // Pthreads doesn't define any way to do this, so we just have to
3181debfc3dSmrg    // assume native_handle_type is LessThanComparable.
3191debfc3dSmrg    return __x._M_thread < __y._M_thread;
3201debfc3dSmrg  }
3211debfc3dSmrg
3221debfc3dSmrg  inline bool
3231debfc3dSmrg  operator<=(thread::id __x, thread::id __y) noexcept
3241debfc3dSmrg  { return !(__y < __x); }
3251debfc3dSmrg
3261debfc3dSmrg  inline bool
3271debfc3dSmrg  operator>(thread::id __x, thread::id __y) noexcept
3281debfc3dSmrg  { return __y < __x; }
3291debfc3dSmrg
3301debfc3dSmrg  inline bool
3311debfc3dSmrg  operator>=(thread::id __x, thread::id __y) noexcept
3321debfc3dSmrg  { return !(__x < __y); }
333*8feb0f0bSmrg#endif // __cpp_lib_three_way_comparison
3341debfc3dSmrg
3351debfc3dSmrg  // DR 889.
3361debfc3dSmrg  /// std::hash specialization for thread::id.
3371debfc3dSmrg  template<>
3381debfc3dSmrg    struct hash<thread::id>
3391debfc3dSmrg    : public __hash_base<size_t, thread::id>
3401debfc3dSmrg    {
3411debfc3dSmrg      size_t
3421debfc3dSmrg      operator()(const thread::id& __id) const noexcept
3431debfc3dSmrg      { return std::_Hash_impl::hash(__id._M_thread); }
3441debfc3dSmrg    };
3451debfc3dSmrg
3461debfc3dSmrg  template<class _CharT, class _Traits>
3471debfc3dSmrg    inline basic_ostream<_CharT, _Traits>&
3481debfc3dSmrg    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
3491debfc3dSmrg    {
3501debfc3dSmrg      if (__id == thread::id())
3511debfc3dSmrg	return __out << "thread::id of a non-executing thread";
3521debfc3dSmrg      else
3531debfc3dSmrg	return __out << __id._M_thread;
3541debfc3dSmrg    }
3551debfc3dSmrg
3561debfc3dSmrg  /** @namespace std::this_thread
357*8feb0f0bSmrg   *  @brief ISO C++ 2011 namespace for interacting with the current thread
358*8feb0f0bSmrg   *
359*8feb0f0bSmrg   *  C++11 30.3.2 [thread.thread.this] Namespace this_thread.
3601debfc3dSmrg   */
3611debfc3dSmrg  namespace this_thread
3621debfc3dSmrg  {
3631debfc3dSmrg    /// get_id
3641debfc3dSmrg    inline thread::id
3651debfc3dSmrg    get_id() noexcept
3661debfc3dSmrg    {
367*8feb0f0bSmrg#ifdef _GLIBCXX_NATIVE_THREAD_ID
368*8feb0f0bSmrg      return thread::id(_GLIBCXX_NATIVE_THREAD_ID);
369*8feb0f0bSmrg#else
3701debfc3dSmrg      return thread::id(__gthread_self());
371*8feb0f0bSmrg#endif
3721debfc3dSmrg    }
3731debfc3dSmrg
3741debfc3dSmrg    /// yield
3751debfc3dSmrg    inline void
3761debfc3dSmrg    yield() noexcept
3771debfc3dSmrg    {
3781debfc3dSmrg#ifdef _GLIBCXX_USE_SCHED_YIELD
3791debfc3dSmrg      __gthread_yield();
3801debfc3dSmrg#endif
3811debfc3dSmrg    }
3821debfc3dSmrg
3831debfc3dSmrg    void
3841debfc3dSmrg    __sleep_for(chrono::seconds, chrono::nanoseconds);
3851debfc3dSmrg
3861debfc3dSmrg    /// sleep_for
3871debfc3dSmrg    template<typename _Rep, typename _Period>
3881debfc3dSmrg      inline void
3891debfc3dSmrg      sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
3901debfc3dSmrg      {
3911debfc3dSmrg	if (__rtime <= __rtime.zero())
3921debfc3dSmrg	  return;
3931debfc3dSmrg	auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
3941debfc3dSmrg	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
3951debfc3dSmrg#ifdef _GLIBCXX_USE_NANOSLEEP
3961debfc3dSmrg	__gthread_time_t __ts =
3971debfc3dSmrg	  {
3981debfc3dSmrg	    static_cast<std::time_t>(__s.count()),
3991debfc3dSmrg	    static_cast<long>(__ns.count())
4001debfc3dSmrg	  };
4011debfc3dSmrg	while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
4021debfc3dSmrg	  { }
4031debfc3dSmrg#else
4041debfc3dSmrg	__sleep_for(__s, __ns);
4051debfc3dSmrg#endif
4061debfc3dSmrg      }
4071debfc3dSmrg
4081debfc3dSmrg    /// sleep_until
4091debfc3dSmrg    template<typename _Clock, typename _Duration>
4101debfc3dSmrg      inline void
4111debfc3dSmrg      sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
4121debfc3dSmrg      {
413*8feb0f0bSmrg#if __cplusplus > 201703L
414*8feb0f0bSmrg	static_assert(chrono::is_clock_v<_Clock>);
415*8feb0f0bSmrg#endif
4161debfc3dSmrg	auto __now = _Clock::now();
4171debfc3dSmrg	if (_Clock::is_steady)
4181debfc3dSmrg	  {
4191debfc3dSmrg	    if (__now < __atime)
4201debfc3dSmrg	      sleep_for(__atime - __now);
4211debfc3dSmrg	    return;
4221debfc3dSmrg	  }
4231debfc3dSmrg	while (__now < __atime)
4241debfc3dSmrg	  {
4251debfc3dSmrg	    sleep_for(__atime - __now);
4261debfc3dSmrg	    __now = _Clock::now();
4271debfc3dSmrg	  }
4281debfc3dSmrg      }
4291debfc3dSmrg  }
4301debfc3dSmrg
431*8feb0f0bSmrg  /// @} group threads
4321debfc3dSmrg
433*8feb0f0bSmrg#ifdef __cpp_lib_jthread
434*8feb0f0bSmrg
435*8feb0f0bSmrg  class jthread
436*8feb0f0bSmrg  {
437*8feb0f0bSmrg  public:
438*8feb0f0bSmrg    using id = thread::id;
439*8feb0f0bSmrg    using native_handle_type = thread::native_handle_type;
440*8feb0f0bSmrg
441*8feb0f0bSmrg    jthread() noexcept
442*8feb0f0bSmrg    : _M_stop_source{nostopstate}
443*8feb0f0bSmrg    { }
444*8feb0f0bSmrg
445*8feb0f0bSmrg    template<typename _Callable, typename... _Args,
446*8feb0f0bSmrg	     typename = enable_if_t<!is_same_v<remove_cvref_t<_Callable>,
447*8feb0f0bSmrg					       jthread>>>
448*8feb0f0bSmrg      explicit
449*8feb0f0bSmrg      jthread(_Callable&& __f, _Args&&... __args)
450*8feb0f0bSmrg      : _M_thread{_S_create(_M_stop_source, std::forward<_Callable>(__f),
451*8feb0f0bSmrg			    std::forward<_Args>(__args)...)}
452*8feb0f0bSmrg      { }
453*8feb0f0bSmrg
454*8feb0f0bSmrg    jthread(const jthread&) = delete;
455*8feb0f0bSmrg    jthread(jthread&&) noexcept = default;
456*8feb0f0bSmrg
457*8feb0f0bSmrg    ~jthread()
458*8feb0f0bSmrg    {
459*8feb0f0bSmrg      if (joinable())
460*8feb0f0bSmrg        {
461*8feb0f0bSmrg          request_stop();
462*8feb0f0bSmrg          join();
463*8feb0f0bSmrg        }
464*8feb0f0bSmrg    }
465*8feb0f0bSmrg
466*8feb0f0bSmrg    jthread&
467*8feb0f0bSmrg    operator=(const jthread&) = delete;
468*8feb0f0bSmrg
469*8feb0f0bSmrg    jthread&
470*8feb0f0bSmrg    operator=(jthread&& __other) noexcept
471*8feb0f0bSmrg    {
472*8feb0f0bSmrg      std::jthread(std::move(__other)).swap(*this);
473*8feb0f0bSmrg      return *this;
474*8feb0f0bSmrg    }
475*8feb0f0bSmrg
476*8feb0f0bSmrg    void
477*8feb0f0bSmrg    swap(jthread& __other) noexcept
478*8feb0f0bSmrg    {
479*8feb0f0bSmrg      std::swap(_M_stop_source, __other._M_stop_source);
480*8feb0f0bSmrg      std::swap(_M_thread, __other._M_thread);
481*8feb0f0bSmrg    }
482*8feb0f0bSmrg
483*8feb0f0bSmrg    [[nodiscard]] bool
484*8feb0f0bSmrg    joinable() const noexcept
485*8feb0f0bSmrg    {
486*8feb0f0bSmrg      return _M_thread.joinable();
487*8feb0f0bSmrg    }
488*8feb0f0bSmrg
489*8feb0f0bSmrg    void
490*8feb0f0bSmrg    join()
491*8feb0f0bSmrg    {
492*8feb0f0bSmrg      _M_thread.join();
493*8feb0f0bSmrg    }
494*8feb0f0bSmrg
495*8feb0f0bSmrg    void
496*8feb0f0bSmrg    detach()
497*8feb0f0bSmrg    {
498*8feb0f0bSmrg      _M_thread.detach();
499*8feb0f0bSmrg    }
500*8feb0f0bSmrg
501*8feb0f0bSmrg    [[nodiscard]] id
502*8feb0f0bSmrg    get_id() const noexcept
503*8feb0f0bSmrg    {
504*8feb0f0bSmrg      return _M_thread.get_id();
505*8feb0f0bSmrg    }
506*8feb0f0bSmrg
507*8feb0f0bSmrg    [[nodiscard]] native_handle_type
508*8feb0f0bSmrg    native_handle()
509*8feb0f0bSmrg    {
510*8feb0f0bSmrg      return _M_thread.native_handle();
511*8feb0f0bSmrg    }
512*8feb0f0bSmrg
513*8feb0f0bSmrg    [[nodiscard]] static unsigned
514*8feb0f0bSmrg    hardware_concurrency() noexcept
515*8feb0f0bSmrg    {
516*8feb0f0bSmrg      return thread::hardware_concurrency();
517*8feb0f0bSmrg    }
518*8feb0f0bSmrg
519*8feb0f0bSmrg    [[nodiscard]] stop_source
520*8feb0f0bSmrg    get_stop_source() noexcept
521*8feb0f0bSmrg    {
522*8feb0f0bSmrg      return _M_stop_source;
523*8feb0f0bSmrg    }
524*8feb0f0bSmrg
525*8feb0f0bSmrg    [[nodiscard]] stop_token
526*8feb0f0bSmrg    get_stop_token() const noexcept
527*8feb0f0bSmrg    {
528*8feb0f0bSmrg      return _M_stop_source.get_token();
529*8feb0f0bSmrg    }
530*8feb0f0bSmrg
531*8feb0f0bSmrg    bool request_stop() noexcept
532*8feb0f0bSmrg    {
533*8feb0f0bSmrg      return _M_stop_source.request_stop();
534*8feb0f0bSmrg    }
535*8feb0f0bSmrg
536*8feb0f0bSmrg    friend void swap(jthread& __lhs, jthread& __rhs) noexcept
537*8feb0f0bSmrg    {
538*8feb0f0bSmrg      __lhs.swap(__rhs);
539*8feb0f0bSmrg    }
540*8feb0f0bSmrg
541*8feb0f0bSmrg  private:
542*8feb0f0bSmrg    template<typename _Callable, typename... _Args>
543*8feb0f0bSmrg      static thread
544*8feb0f0bSmrg      _S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
545*8feb0f0bSmrg      {
546*8feb0f0bSmrg	if constexpr(is_invocable_v<decay_t<_Callable>, stop_token,
547*8feb0f0bSmrg				    decay_t<_Args>...>)
548*8feb0f0bSmrg	  return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
549*8feb0f0bSmrg			std::forward<_Args>(__args)...};
550*8feb0f0bSmrg	else
551*8feb0f0bSmrg	  {
552*8feb0f0bSmrg	    static_assert(is_invocable_v<decay_t<_Callable>,
553*8feb0f0bSmrg					 decay_t<_Args>...>,
554*8feb0f0bSmrg			  "std::thread arguments must be invocable after"
555*8feb0f0bSmrg			  " conversion to rvalues");
556*8feb0f0bSmrg	    return thread{std::forward<_Callable>(__f),
557*8feb0f0bSmrg			  std::forward<_Args>(__args)...};
558*8feb0f0bSmrg	  }
559*8feb0f0bSmrg      }
560*8feb0f0bSmrg
561*8feb0f0bSmrg    stop_source _M_stop_source;
562*8feb0f0bSmrg    thread _M_thread;
563*8feb0f0bSmrg  };
564*8feb0f0bSmrg#endif // __cpp_lib_jthread
565a2dc1f3fSmrg_GLIBCXX_END_NAMESPACE_VERSION
5661debfc3dSmrg} // namespace
567c0a68be4Smrg#endif // _GLIBCXX_HAS_GTHREADS
5681debfc3dSmrg#endif // C++11
5691debfc3dSmrg#endif // _GLIBCXX_THREAD
570