29 #ifndef _GLIBCXX_STOP_TOKEN
30 #define _GLIBCXX_STOP_TOKEN
32 #if __cplusplus > 201703L
38 #include <bits/shared_ptr.h>
40 #ifdef _GLIBCXX_HAS_GTHREADS
41 # define __cpp_lib_jthread 201907L
44 namespace std _GLIBCXX_VISIBILITY(default)
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 struct nostopstate_t {
explicit nostopstate_t() =
default; };
50 inline constexpr nostopstate_t nostopstate{};
56 stop_token() noexcept = default;
58 stop_token(const stop_token& __other) noexcept = default;
59 stop_token(stop_token&& __other) noexcept = default;
61 ~stop_token() = default;
64 operator=(const stop_token& __rhs) noexcept = default;
67 operator=(stop_token&& __rhs) noexcept = default;
71 stop_possible() const noexcept
73 return static_cast<bool>(_M_state);
78 stop_requested() const noexcept
80 return stop_possible() && _M_state->_M_stop_requested();
84 swap(stop_token& __rhs) noexcept
85 { _M_state.swap(__rhs._M_state); }
89 operator==(
const stop_token& __a,
const stop_token& __b)
91 return __a._M_state == __b._M_state;
96 operator!=(
const stop_token& __a,
const stop_token& __b)
98 return __a._M_state != __b._M_state;
102 swap(stop_token& __lhs, stop_token& __rhs) noexcept
103 { __lhs.swap(__rhs); }
106 friend class stop_source;
107 template<
typename _Callback>
108 friend class stop_callback;
112 void(*_M_callback)(_Stop_cb*);
113 _Stop_cb* _M_prev =
nullptr;
114 _Stop_cb* _M_next =
nullptr;
116 template<
typename _Cb>
122 _M_linked() const noexcept
124 return (_M_prev !=
nullptr)
125 || (_M_next !=
nullptr);
129 _S_execute(_Stop_cb* __cb) noexcept
131 __cb->_M_callback(__cb);
132 __cb->_M_prev = __cb->_M_next =
nullptr;
139 _Stop_cb* _M_head =
nullptr;
140 #ifdef _GLIBCXX_HAS_GTHREADS
144 _Stop_state_t() =
default;
147 _M_stop_requested() noexcept
155 bool __stopped =
false;
156 if (_M_stopped.compare_exchange_strong(__stopped,
true))
158 #ifdef _GLIBCXX_HAS_GTHREADS
164 _M_head = _M_head->_M_next;
165 _Stop_cb::_S_execute(__p);
173 _M_register_callback(_Stop_cb* __cb)
175 #ifdef _GLIBCXX_HAS_GTHREADS
181 __cb->_M_next = _M_head;
184 _M_head->_M_prev = __cb;
191 _M_remove_callback(_Stop_cb* __cb)
193 #ifdef _GLIBCXX_HAS_GTHREADS
198 _M_head = _M_head->_M_next;
201 _M_head->_M_prev =
nullptr;
204 else if (!__cb->_M_linked())
210 __cb->_M_prev->_M_next = __cb->_M_next;
213 __cb->_M_next->_M_prev = __cb->_M_prev;
220 _Stop_state _M_state;
223 stop_token(
const _Stop_state& __state) noexcept
233 : _M_state(
std::make_shared<stop_token::_Stop_state_t>())
236 explicit stop_source(std::nostopstate_t) noexcept
239 stop_source(
const stop_source& __other) noexcept
240 : _M_state(__other._M_state)
243 stop_source(stop_source&& __other) noexcept
248 operator=(
const stop_source& __rhs) noexcept
250 if (_M_state != __rhs._M_state)
251 _M_state = __rhs._M_state;
256 operator=(stop_source&& __rhs) noexcept
258 std::swap(_M_state, __rhs._M_state);
264 stop_possible() const noexcept
266 return static_cast<bool>(_M_state);
271 stop_requested() const noexcept
273 return stop_possible() && _M_state->_M_stop_requested();
277 request_stop() const noexcept
280 return _M_state->_M_request_stop();
286 get_token() const noexcept
288 return stop_token{_M_state};
292 swap(stop_source& __other) noexcept
294 _M_state.swap(__other._M_state);
299 operator==(
const stop_source& __a,
const stop_source& __b) noexcept
301 return __a._M_state == __b._M_state;
306 operator!=(
const stop_source& __a,
const stop_source& __b) noexcept
308 return __a._M_state != __b._M_state;
312 swap(stop_source& __lhs, stop_source& __rhs) noexcept
318 stop_token::_Stop_state _M_state;
322 template<
typename _Callback>
323 class [[nodiscard]] stop_callback
324 :
private stop_token::_Stop_cb
327 using callback_type = _Callback;
329 template<
typename _Cb,
330 enable_if_t<is_constructible_v<_Callback, _Cb>,
int> = 0>
332 stop_callback(
const stop_token& __token, _Cb&& __cb)
333 noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
334 : _Stop_cb(&_S_execute), _M_cb(
std::
forward<_Cb>(__cb))
336 if (
auto __state = __token._M_state)
338 if (__state->_M_stop_requested())
340 else if (__state->_M_register_callback(
this))
341 _M_state.swap(__state);
345 template<
typename _Cb,
346 enable_if_t<is_constructible_v<_Callback, _Cb>,
int> = 0>
348 stop_callback(stop_token&& __token, _Cb&& __cb)
349 noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
350 : _Stop_cb(&_S_execute), _M_cb(
std::
forward<_Cb>(__cb))
352 if (
auto& __state = __token._M_state)
354 if (__state->_M_stop_requested())
356 else if (__state->_M_register_callback(
this))
357 _M_state.swap(__state);
365 _M_state->_M_remove_callback(
this);
369 stop_callback(
const stop_callback&) =
delete;
370 stop_callback& operator=(
const stop_callback&) =
delete;
371 stop_callback(stop_callback&&) =
delete;
372 stop_callback& operator=(stop_callback&&) =
delete;
376 stop_token::_Stop_state _M_state =
nullptr;
379 _S_execute(_Stop_cb* __that) noexcept
381 static_cast<stop_callback*>(__that)->_M_cb();
385 template<
typename _Callback>
386 stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
388 _GLIBCXX_END_NAMESPACE_VERSION
390 #endif // __cplusplus > 201703L
391 #endif // _GLIBCXX_STOP_TOKEN