xref: /freebsd-src/contrib/llvm-project/libcxx/include/__stop_token/stop_callback.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric // -*- C++ -*-
206c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
306c3fb27SDimitry Andric //
406c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
506c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
606c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
706c3fb27SDimitry Andric //
806c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
906c3fb27SDimitry Andric 
1006c3fb27SDimitry Andric #ifndef _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
1106c3fb27SDimitry Andric #define _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
1206c3fb27SDimitry Andric 
1306c3fb27SDimitry Andric #include <__concepts/constructible.h>
1406c3fb27SDimitry Andric #include <__concepts/destructible.h>
1506c3fb27SDimitry Andric #include <__concepts/invocable.h>
1606c3fb27SDimitry Andric #include <__config>
1706c3fb27SDimitry Andric #include <__stop_token/intrusive_shared_ptr.h>
1806c3fb27SDimitry Andric #include <__stop_token/stop_state.h>
1906c3fb27SDimitry Andric #include <__stop_token/stop_token.h>
2006c3fb27SDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
2106c3fb27SDimitry Andric #include <__utility/forward.h>
2206c3fb27SDimitry Andric #include <__utility/move.h>
23*0fca6ea1SDimitry Andric #include <__utility/private_constructor_tag.h>
2406c3fb27SDimitry Andric 
2506c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2606c3fb27SDimitry Andric #  pragma GCC system_header
2706c3fb27SDimitry Andric #endif
2806c3fb27SDimitry Andric 
295f757f3fSDimitry Andric _LIBCPP_PUSH_MACROS
305f757f3fSDimitry Andric #include <__undef_macros>
315f757f3fSDimitry Andric 
3206c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
3306c3fb27SDimitry Andric 
345f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
3506c3fb27SDimitry Andric 
3606c3fb27SDimitry Andric template <class _Callback>
3706c3fb27SDimitry Andric class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
3806c3fb27SDimitry Andric   static_assert(invocable<_Callback>,
3906c3fb27SDimitry Andric                 "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
4006c3fb27SDimitry Andric                 "satisfies invocable.");
4106c3fb27SDimitry Andric   static_assert(destructible<_Callback>,
4206c3fb27SDimitry Andric                 "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
4306c3fb27SDimitry Andric                 "satisfies destructible.");
4406c3fb27SDimitry Andric 
4506c3fb27SDimitry Andric public:
4606c3fb27SDimitry Andric   using callback_type = _Callback;
4706c3fb27SDimitry Andric 
4806c3fb27SDimitry Andric   template <class _Cb>
4906c3fb27SDimitry Andric     requires constructible_from<_Callback, _Cb>
5006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(const stop_token& __st,
5106c3fb27SDimitry Andric                                                _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
52*0fca6ea1SDimitry Andric       : stop_callback(__private_constructor_tag{}, __st.__state_, std::forward<_Cb>(__cb)) {}
5306c3fb27SDimitry Andric 
5406c3fb27SDimitry Andric   template <class _Cb>
5506c3fb27SDimitry Andric     requires constructible_from<_Callback, _Cb>
5606c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(stop_token&& __st,
5706c3fb27SDimitry Andric                                                _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
58*0fca6ea1SDimitry Andric       : stop_callback(__private_constructor_tag{}, std::move(__st.__state_), std::forward<_Cb>(__cb)) {}
5906c3fb27SDimitry Andric 
6006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI ~stop_callback() {
6106c3fb27SDimitry Andric     if (__state_) {
6206c3fb27SDimitry Andric       __state_->__remove_callback(this);
6306c3fb27SDimitry Andric     }
6406c3fb27SDimitry Andric   }
6506c3fb27SDimitry Andric 
6606c3fb27SDimitry Andric   stop_callback(const stop_callback&)            = delete;
6706c3fb27SDimitry Andric   stop_callback(stop_callback&&)                 = delete;
6806c3fb27SDimitry Andric   stop_callback& operator=(const stop_callback&) = delete;
6906c3fb27SDimitry Andric   stop_callback& operator=(stop_callback&&)      = delete;
7006c3fb27SDimitry Andric 
7106c3fb27SDimitry Andric private:
7206c3fb27SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _Callback __callback_;
7306c3fb27SDimitry Andric   __intrusive_shared_ptr<__stop_state> __state_;
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric   friend __stop_callback_base;
7606c3fb27SDimitry Andric 
7706c3fb27SDimitry Andric   template <class _StatePtr, class _Cb>
78*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(__private_constructor_tag, _StatePtr&& __state, _Cb&& __cb) noexcept(
7906c3fb27SDimitry Andric       is_nothrow_constructible_v<_Callback, _Cb>)
8006c3fb27SDimitry Andric       : __stop_callback_base([](__stop_callback_base* __cb_base) noexcept {
8106c3fb27SDimitry Andric           // stop callback is supposed to only be called once
8206c3fb27SDimitry Andric           std::forward<_Callback>(static_cast<stop_callback*>(__cb_base)->__callback_)();
8306c3fb27SDimitry Andric         }),
8406c3fb27SDimitry Andric         __callback_(std::forward<_Cb>(__cb)),
8506c3fb27SDimitry Andric         __state_() {
8606c3fb27SDimitry Andric     if (__state && __state->__add_callback(this)) {
8706c3fb27SDimitry Andric       // st.stop_requested() was false and this is successfully added to the linked list
8806c3fb27SDimitry Andric       __state_ = std::forward<_StatePtr>(__state);
8906c3fb27SDimitry Andric     }
9006c3fb27SDimitry Andric   }
9106c3fb27SDimitry Andric };
9206c3fb27SDimitry Andric 
9306c3fb27SDimitry Andric template <class _Callback>
9406c3fb27SDimitry Andric _LIBCPP_AVAILABILITY_SYNC stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
9506c3fb27SDimitry Andric 
9606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
9706c3fb27SDimitry Andric 
9806c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
9906c3fb27SDimitry Andric 
1005f757f3fSDimitry Andric _LIBCPP_POP_MACROS
1015f757f3fSDimitry Andric 
1025f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
103