thread 7.3 KB

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