Home | History | Annotate | Line # | Download | only in std
      1   1.1  mrg // <thread> -*- C++ -*-
      2   1.1  mrg 
      3  1.13  mrg // Copyright (C) 2008-2022 Free Software Foundation, Inc.
      4   1.1  mrg //
      5   1.1  mrg // This file is part of the GNU ISO C++ Library.  This library is free
      6   1.1  mrg // software; you can redistribute it and/or modify it under the
      7   1.1  mrg // terms of the GNU General Public License as published by the
      8   1.1  mrg // Free Software Foundation; either version 3, or (at your option)
      9   1.1  mrg // any later version.
     10   1.1  mrg 
     11   1.1  mrg // This library is distributed in the hope that it will be useful,
     12   1.1  mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  mrg // GNU General Public License for more details.
     15   1.1  mrg 
     16   1.1  mrg // Under Section 7 of GPL version 3, you are granted additional
     17   1.1  mrg // permissions described in the GCC Runtime Library Exception, version
     18   1.1  mrg // 3.1, as published by the Free Software Foundation.
     19   1.1  mrg 
     20   1.1  mrg // You should have received a copy of the GNU General Public License and
     21   1.1  mrg // a copy of the GCC Runtime Library Exception along with this program;
     22   1.1  mrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23   1.1  mrg // <http://www.gnu.org/licenses/>.
     24   1.1  mrg 
     25   1.3  mrg /** @file include/thread
     26   1.1  mrg  *  This is a Standard C++ Library header.
     27   1.1  mrg  */
     28   1.1  mrg 
     29   1.1  mrg #ifndef _GLIBCXX_THREAD
     30   1.1  mrg #define _GLIBCXX_THREAD 1
     31   1.1  mrg 
     32   1.1  mrg #pragma GCC system_header
     33   1.1  mrg 
     34   1.3  mrg #if __cplusplus < 201103L
     35   1.1  mrg # include <bits/c++0x_warning.h>
     36   1.1  mrg #else
     37   1.1  mrg 
     38  1.12  mrg #if __cplusplus > 201703L
     39  1.12  mrg # include <compare>	// std::strong_ordering
     40  1.12  mrg # include <stop_token>	// std::stop_source, std::stop_token, std::nostopstate
     41  1.12  mrg #endif
     42  1.12  mrg 
     43  1.13  mrg #include <bits/std_thread.h> // std::thread, get_id, yield
     44  1.13  mrg #include <bits/this_thread_sleep.h> // std::this_thread::sleep_for, sleep_until
     45   1.1  mrg 
     46   1.3  mrg namespace std _GLIBCXX_VISIBILITY(default)
     47   1.1  mrg {
     48   1.3  mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
     49   1.3  mrg 
     50   1.1  mrg   /**
     51   1.1  mrg    * @defgroup threads Threads
     52   1.1  mrg    * @ingroup concurrency
     53  1.13  mrg    * @since C++11
     54   1.1  mrg    *
     55   1.1  mrg    * Classes for thread support.
     56   1.1  mrg    * @{
     57   1.1  mrg    */
     58   1.1  mrg 
     59  1.13  mrg   // std::thread is defined in <bits/std_thread.h>
     60   1.1  mrg 
     61  1.13  mrg   /// @relates std::thread::id @{
     62   1.9  mrg 
     63  1.12  mrg #if __cpp_lib_three_way_comparison
     64  1.12  mrg   inline strong_ordering
     65  1.12  mrg   operator<=>(thread::id __x, thread::id __y) noexcept
     66  1.12  mrg   { return __x._M_thread <=> __y._M_thread; }
     67  1.12  mrg #else
     68   1.9  mrg   inline bool
     69   1.3  mrg   operator!=(thread::id __x, thread::id __y) noexcept
     70   1.1  mrg   { return !(__x == __y); }
     71   1.1  mrg 
     72   1.1  mrg   inline bool
     73   1.9  mrg   operator<(thread::id __x, thread::id __y) noexcept
     74   1.9  mrg   {
     75   1.9  mrg     // Pthreads doesn't define any way to do this, so we just have to
     76   1.9  mrg     // assume native_handle_type is LessThanComparable.
     77   1.9  mrg     return __x._M_thread < __y._M_thread;
     78   1.9  mrg   }
     79   1.9  mrg 
     80   1.9  mrg   inline bool
     81   1.3  mrg   operator<=(thread::id __x, thread::id __y) noexcept
     82   1.1  mrg   { return !(__y < __x); }
     83   1.1  mrg 
     84   1.1  mrg   inline bool
     85   1.3  mrg   operator>(thread::id __x, thread::id __y) noexcept
     86   1.1  mrg   { return __y < __x; }
     87   1.1  mrg 
     88   1.1  mrg   inline bool
     89   1.3  mrg   operator>=(thread::id __x, thread::id __y) noexcept
     90   1.1  mrg   { return !(__x < __y); }
     91  1.12  mrg #endif // __cpp_lib_three_way_comparison
     92   1.1  mrg 
     93   1.1  mrg   template<class _CharT, class _Traits>
     94   1.1  mrg     inline basic_ostream<_CharT, _Traits>&
     95   1.1  mrg     operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
     96   1.1  mrg     {
     97   1.1  mrg       if (__id == thread::id())
     98   1.1  mrg 	return __out << "thread::id of a non-executing thread";
     99   1.1  mrg       else
    100   1.1  mrg 	return __out << __id._M_thread;
    101   1.1  mrg     }
    102  1.13  mrg   /// @}
    103   1.1  mrg 
    104  1.13  mrg #ifdef __cpp_lib_jthread
    105   1.1  mrg 
    106  1.13  mrg   /// @cond undocumented
    107  1.13  mrg #ifndef __STRICT_ANSI__
    108  1.13  mrg     template<typename _Callable, typename... _Args>
    109  1.13  mrg       constexpr bool __pmf_expects_stop_token = false;
    110   1.1  mrg 
    111  1.13  mrg     template<typename _Callable, typename _Obj, typename... _Args>
    112  1.13  mrg       constexpr bool __pmf_expects_stop_token<_Callable, _Obj, _Args...>
    113  1.13  mrg 	= __and_<is_member_function_pointer<remove_reference_t<_Callable>>,
    114  1.13  mrg 		 is_invocable<_Callable, _Obj, stop_token, _Args...>>::value;
    115   1.3  mrg #endif
    116  1.13  mrg     /// @endcond
    117  1.12  mrg 
    118  1.13  mrg   /** A thread with cancellation and automatic joining.
    119  1.13  mrg    *
    120  1.13  mrg    * Unlike `std::thread`, destroying a joinable `std::jthread` will not
    121  1.13  mrg    * terminate the process. Instead, it will try to request its thread to
    122  1.13  mrg    * stop, then will join it.
    123  1.13  mrg    *
    124  1.13  mrg    * A `std::jthread` has a `std::stop_source` member which will be passed
    125  1.13  mrg    * as the first argument to the callable that runs in the new thread
    126  1.13  mrg    * (as long as the callable will accept that argument). That can then
    127  1.13  mrg    * be used to send a stop request that the new thread can test for.
    128  1.13  mrg    *
    129  1.13  mrg    * @headerfile thread
    130  1.13  mrg    * @since C++20
    131  1.13  mrg    */
    132  1.12  mrg   class jthread
    133  1.12  mrg   {
    134  1.12  mrg   public:
    135  1.12  mrg     using id = thread::id;
    136  1.12  mrg     using native_handle_type = thread::native_handle_type;
    137  1.12  mrg 
    138  1.12  mrg     jthread() noexcept
    139  1.12  mrg     : _M_stop_source{nostopstate}
    140  1.12  mrg     { }
    141  1.12  mrg 
    142  1.12  mrg     template<typename _Callable, typename... _Args,
    143  1.12  mrg 	     typename = enable_if_t<!is_same_v<remove_cvref_t<_Callable>,
    144  1.12  mrg 					       jthread>>>
    145  1.12  mrg       explicit
    146  1.12  mrg       jthread(_Callable&& __f, _Args&&... __args)
    147  1.12  mrg       : _M_thread{_S_create(_M_stop_source, std::forward<_Callable>(__f),
    148  1.12  mrg 			    std::forward<_Args>(__args)...)}
    149  1.12  mrg       { }
    150  1.12  mrg 
    151  1.12  mrg     jthread(const jthread&) = delete;
    152  1.12  mrg     jthread(jthread&&) noexcept = default;
    153  1.12  mrg 
    154  1.12  mrg     ~jthread()
    155  1.12  mrg     {
    156  1.12  mrg       if (joinable())
    157  1.12  mrg         {
    158  1.12  mrg           request_stop();
    159  1.12  mrg           join();
    160  1.12  mrg         }
    161  1.12  mrg     }
    162  1.12  mrg 
    163  1.12  mrg     jthread&
    164  1.12  mrg     operator=(const jthread&) = delete;
    165  1.12  mrg 
    166  1.12  mrg     jthread&
    167  1.12  mrg     operator=(jthread&& __other) noexcept
    168  1.12  mrg     {
    169  1.12  mrg       std::jthread(std::move(__other)).swap(*this);
    170  1.12  mrg       return *this;
    171  1.12  mrg     }
    172  1.12  mrg 
    173  1.12  mrg     void
    174  1.12  mrg     swap(jthread& __other) noexcept
    175  1.12  mrg     {
    176  1.12  mrg       std::swap(_M_stop_source, __other._M_stop_source);
    177  1.12  mrg       std::swap(_M_thread, __other._M_thread);
    178  1.12  mrg     }
    179  1.12  mrg 
    180  1.12  mrg     [[nodiscard]] bool
    181  1.12  mrg     joinable() const noexcept
    182  1.12  mrg     {
    183  1.12  mrg       return _M_thread.joinable();
    184  1.12  mrg     }
    185  1.12  mrg 
    186  1.12  mrg     void
    187  1.12  mrg     join()
    188  1.12  mrg     {
    189  1.12  mrg       _M_thread.join();
    190  1.12  mrg     }
    191  1.12  mrg 
    192  1.12  mrg     void
    193  1.12  mrg     detach()
    194  1.12  mrg     {
    195  1.12  mrg       _M_thread.detach();
    196  1.12  mrg     }
    197  1.12  mrg 
    198  1.12  mrg     [[nodiscard]] id
    199  1.12  mrg     get_id() const noexcept
    200  1.12  mrg     {
    201  1.12  mrg       return _M_thread.get_id();
    202  1.12  mrg     }
    203  1.12  mrg 
    204  1.12  mrg     [[nodiscard]] native_handle_type
    205  1.12  mrg     native_handle()
    206  1.12  mrg     {
    207  1.12  mrg       return _M_thread.native_handle();
    208  1.12  mrg     }
    209  1.12  mrg 
    210  1.12  mrg     [[nodiscard]] static unsigned
    211  1.12  mrg     hardware_concurrency() noexcept
    212  1.12  mrg     {
    213  1.12  mrg       return thread::hardware_concurrency();
    214  1.12  mrg     }
    215  1.12  mrg 
    216  1.12  mrg     [[nodiscard]] stop_source
    217  1.12  mrg     get_stop_source() noexcept
    218  1.12  mrg     {
    219  1.12  mrg       return _M_stop_source;
    220  1.12  mrg     }
    221  1.12  mrg 
    222  1.12  mrg     [[nodiscard]] stop_token
    223  1.12  mrg     get_stop_token() const noexcept
    224  1.12  mrg     {
    225  1.12  mrg       return _M_stop_source.get_token();
    226  1.12  mrg     }
    227  1.12  mrg 
    228  1.12  mrg     bool request_stop() noexcept
    229  1.12  mrg     {
    230  1.12  mrg       return _M_stop_source.request_stop();
    231  1.12  mrg     }
    232  1.12  mrg 
    233  1.12  mrg     friend void swap(jthread& __lhs, jthread& __rhs) noexcept
    234  1.12  mrg     {
    235  1.12  mrg       __lhs.swap(__rhs);
    236  1.12  mrg     }
    237   1.3  mrg 
    238  1.12  mrg   private:
    239  1.12  mrg     template<typename _Callable, typename... _Args>
    240  1.12  mrg       static thread
    241  1.12  mrg       _S_create(stop_source& __ssrc, _Callable&& __f, _Args&&... __args)
    242  1.12  mrg       {
    243  1.13  mrg #ifndef __STRICT_ANSI__
    244  1.13  mrg 	if constexpr (__pmf_expects_stop_token<_Callable, _Args...>)
    245  1.13  mrg 	  return _S_create_pmf(__ssrc, __f, std::forward<_Args>(__args)...);
    246  1.13  mrg 	else
    247  1.13  mrg #endif
    248  1.12  mrg 	if constexpr(is_invocable_v<decay_t<_Callable>, stop_token,
    249  1.12  mrg 				    decay_t<_Args>...>)
    250  1.12  mrg 	  return thread{std::forward<_Callable>(__f), __ssrc.get_token(),
    251  1.12  mrg 			std::forward<_Args>(__args)...};
    252  1.12  mrg 	else
    253  1.12  mrg 	  {
    254  1.12  mrg 	    static_assert(is_invocable_v<decay_t<_Callable>,
    255  1.12  mrg 					 decay_t<_Args>...>,
    256  1.13  mrg 			  "std::jthread arguments must be invocable after"
    257  1.12  mrg 			  " conversion to rvalues");
    258  1.12  mrg 	    return thread{std::forward<_Callable>(__f),
    259  1.12  mrg 			  std::forward<_Args>(__args)...};
    260  1.12  mrg 	  }
    261  1.12  mrg       }
    262  1.12  mrg 
    263  1.13  mrg #ifndef __STRICT_ANSI__
    264  1.13  mrg     template<typename _Callable, typename _Obj, typename... _Args>
    265  1.13  mrg       static thread
    266  1.13  mrg       _S_create_pmf(stop_source& __ssrc, _Callable __f, _Obj&& __obj,
    267  1.13  mrg 		    _Args&&... __args)
    268  1.13  mrg       {
    269  1.13  mrg 	return thread{__f, std::forward<_Obj>(__obj), __ssrc.get_token(),
    270  1.13  mrg 		      std::forward<_Args>(__args)...};
    271  1.13  mrg       }
    272  1.13  mrg #endif
    273  1.13  mrg 
    274  1.12  mrg     stop_source _M_stop_source;
    275  1.12  mrg     thread _M_thread;
    276  1.12  mrg   };
    277  1.12  mrg #endif // __cpp_lib_jthread
    278  1.13  mrg 
    279  1.13  mrg   /// @} group threads
    280  1.13  mrg 
    281  1.10  mrg _GLIBCXX_END_NAMESPACE_VERSION
    282   1.3  mrg } // namespace
    283   1.3  mrg #endif // C++11
    284   1.1  mrg #endif // _GLIBCXX_THREAD
    285