xref: /freebsd/contrib/llvm-project/libcxx/include/__stop_token/stop_callback.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
11 #define _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
12 
13 #include <__concepts/constructible.h>
14 #include <__concepts/destructible.h>
15 #include <__concepts/invocable.h>
16 #include <__config>
17 #include <__stop_token/intrusive_shared_ptr.h>
18 #include <__stop_token/stop_state.h>
19 #include <__stop_token/stop_token.h>
20 #include <__type_traits/is_nothrow_constructible.h>
21 #include <__utility/forward.h>
22 #include <__utility/move.h>
23 #include <__utility/private_constructor_tag.h>
24 
25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26 #  pragma GCC system_header
27 #endif
28 
29 _LIBCPP_PUSH_MACROS
30 #include <__undef_macros>
31 
32 _LIBCPP_BEGIN_NAMESPACE_STD
33 
34 #if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
35 
36 template <class _Callback>
37 class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
38   static_assert(invocable<_Callback>,
39                 "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
40                 "satisfies invocable.");
41   static_assert(destructible<_Callback>,
42                 "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
43                 "satisfies destructible.");
44 
45 public:
46   using callback_type = _Callback;
47 
48   template <class _Cb>
49     requires constructible_from<_Callback, _Cb>
50   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(const stop_token& __st,
51                                                _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
52       : stop_callback(__private_constructor_tag{}, __st.__state_, std::forward<_Cb>(__cb)) {}
53 
54   template <class _Cb>
55     requires constructible_from<_Callback, _Cb>
56   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(stop_token&& __st,
57                                                _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
58       : stop_callback(__private_constructor_tag{}, std::move(__st.__state_), std::forward<_Cb>(__cb)) {}
59 
60   _LIBCPP_HIDE_FROM_ABI ~stop_callback() {
61     if (__state_) {
62       __state_->__remove_callback(this);
63     }
64   }
65 
66   stop_callback(const stop_callback&)            = delete;
67   stop_callback(stop_callback&&)                 = delete;
68   stop_callback& operator=(const stop_callback&) = delete;
69   stop_callback& operator=(stop_callback&&)      = delete;
70 
71 private:
72   _LIBCPP_NO_UNIQUE_ADDRESS _Callback __callback_;
73   __intrusive_shared_ptr<__stop_state> __state_;
74 
75   friend __stop_callback_base;
76 
77   template <class _StatePtr, class _Cb>
78   _LIBCPP_HIDE_FROM_ABI explicit stop_callback(__private_constructor_tag, _StatePtr&& __state, _Cb&& __cb) noexcept(
79       is_nothrow_constructible_v<_Callback, _Cb>)
80       : __stop_callback_base([](__stop_callback_base* __cb_base) noexcept {
81           // stop callback is supposed to only be called once
82           std::forward<_Callback>(static_cast<stop_callback*>(__cb_base)->__callback_)();
83         }),
84         __callback_(std::forward<_Cb>(__cb)),
85         __state_() {
86     if (__state && __state->__add_callback(this)) {
87       // st.stop_requested() was false and this is successfully added to the linked list
88       __state_ = std::forward<_StatePtr>(__state);
89     }
90   }
91 };
92 
93 template <class _Callback>
94 _LIBCPP_AVAILABILITY_SYNC stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
95 
96 #endif // _LIBCPP_STD_VER >= 20
97 
98 _LIBCPP_END_NAMESPACE_STD
99 
100 _LIBCPP_POP_MACROS
101 
102 #endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
103