TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Steve Gerbino
3 : // Copyright (c) 2026 Michael Vandeberg
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/corosio
9 : //
10 :
11 : #ifndef BOOST_COROSIO_NATIVE_NATIVE_SIGNAL_SET_HPP
12 : #define BOOST_COROSIO_NATIVE_NATIVE_SIGNAL_SET_HPP
13 :
14 : #include <boost/corosio/signal_set.hpp>
15 : #include <boost/corosio/backend.hpp>
16 : #include <boost/corosio/detail/op_base.hpp>
17 :
18 : #ifndef BOOST_COROSIO_MRDOCS
19 : #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
20 : BOOST_COROSIO_HAS_KQUEUE
21 : #include <boost/corosio/native/detail/posix/posix_signal_service.hpp>
22 : #endif
23 :
24 : #if BOOST_COROSIO_HAS_IOCP
25 : #include <boost/corosio/native/detail/iocp/win_signals.hpp>
26 : #endif
27 : #endif // !BOOST_COROSIO_MRDOCS
28 :
29 : namespace boost::corosio {
30 :
31 : /** Waits for a registered signal, calling the backend directly.
32 :
33 : This class template inherits from @ref signal_set. It shadows the
34 : `wait` operation with a version that calls the backend
35 : implementation directly. The compiler can then inline through the
36 : entire call chain.
37 :
38 : Non-async operations (`add`, `remove`, `clear`, `cancel`)
39 : remain unchanged and dispatch through the compiled library.
40 :
41 : A `native_signal_set` IS-A `signal_set` and can be passed to
42 : any function expecting `signal_set&`.
43 :
44 : @tparam Backend A backend tag value (e.g., `epoll`).
45 :
46 : @par Thread Safety
47 : Same as @ref signal_set.
48 :
49 : @see @ref signal_set, @ref epoll_t, @ref iocp_t
50 : */
51 : template<auto Backend>
52 : class native_signal_set : public signal_set
53 : {
54 : using backend_type = decltype(Backend);
55 : using impl_type = typename backend_type::signal_type;
56 :
57 : impl_type& get_impl() noexcept
58 : {
59 : return *static_cast<impl_type*>(h_.get());
60 : }
61 :
62 : struct native_wait_awaitable
63 : : detail::value_op_base<native_wait_awaitable, int>
64 : {
65 : native_signal_set& self_;
66 :
67 : explicit native_wait_awaitable(native_signal_set& self) noexcept
68 : : self_(self)
69 : {
70 : }
71 :
72 : std::coroutine_handle<>
73 : dispatch(capy::continuation& cont, capy::executor_ref ex) const
74 : {
75 : return self_.get_impl().wait(
76 : cont, ex, this->token_, &this->ec_, &this->value_);
77 : }
78 : };
79 :
80 : public:
81 : /** Construct a native signal set from an execution context.
82 :
83 : @param ctx The execution context that owns this signal set.
84 : */
85 HIT 4 : explicit native_signal_set(capy::execution_context& ctx) : signal_set(ctx)
86 : {
87 4 : }
88 :
89 : /** Construct a native signal set with initial signals.
90 :
91 : For the non-throwing form, construct with the context alone,
92 : then call @ref signal_set::add for each signal.
93 :
94 : @param ctx The execution context that owns this signal set.
95 : @param signal First signal number to add.
96 : @param signals Additional signal numbers to add.
97 :
98 : @throws std::system_error on failure.
99 :
100 : @see @ref signal_set::add
101 : */
102 : template<std::convertible_to<int>... Signals>
103 6 : native_signal_set(
104 : capy::execution_context& ctx, int signal, Signals... signals)
105 6 : : signal_set(ctx, signal, signals...)
106 : {
107 6 : }
108 :
109 : /** Construct a native signal set from an executor.
110 :
111 : @param ex The executor whose context owns the signal set.
112 :
113 : @tparam Ex A type satisfying @ref capy::Executor. Must not
114 : be `native_signal_set` itself (disables implicit
115 : conversion from move).
116 : */
117 : template<class Ex>
118 : requires(!std::same_as<std::remove_cvref_t<Ex>, native_signal_set>) &&
119 : capy::Executor<Ex>
120 2 : explicit native_signal_set(Ex const& ex) : native_signal_set(ex.context())
121 : {
122 2 : }
123 :
124 : /** Construct a native signal set from an executor with initial signals.
125 :
126 : For the non-throwing form, construct with the executor alone,
127 : then call @ref signal_set::add for each signal.
128 :
129 : @param ex The executor whose context owns the signal set.
130 : @param signal First signal number to add.
131 : @param signals Additional signal numbers to add.
132 :
133 : @tparam Ex A type satisfying @ref capy::Executor.
134 :
135 : @throws std::system_error on failure.
136 :
137 : @see @ref signal_set::add
138 : */
139 : template<class Ex, std::convertible_to<int>... Signals>
140 : requires capy::Executor<Ex>
141 2 : native_signal_set(Ex const& ex, int signal, Signals... signals)
142 2 : : native_signal_set(ex.context(), signal, signals...)
143 : {
144 2 : }
145 :
146 : /** Move construct.
147 :
148 : @pre No awaitables returned by the source's methods exist.
149 : @pre The execution context associated with the source must
150 : outlive this signal set.
151 : */
152 : native_signal_set(native_signal_set&&) noexcept = default;
153 :
154 : /** Move assign.
155 :
156 : @pre No awaitables returned by either `*this` or the source's
157 : methods exist.
158 : @pre The execution context associated with the source must
159 : outlive this signal set.
160 : */
161 : native_signal_set& operator=(native_signal_set&&) noexcept = default;
162 :
163 : /// Copy construction is disabled; the handle is uniquely owned.
164 : native_signal_set(native_signal_set const&) = delete;
165 : /// Copy assignment is disabled; the handle is uniquely owned.
166 : native_signal_set& operator=(native_signal_set const&) = delete;
167 :
168 : /** Wait for a signal to be delivered.
169 :
170 : Calls the backend implementation directly, bypassing virtual
171 : dispatch. Otherwise identical to @ref signal_set::wait.
172 :
173 : @return An awaitable yielding `results<int>`.
174 :
175 : This signal set must outlive the returned awaitable.
176 : */
177 : [[nodiscard]] auto wait()
178 : {
179 : return native_wait_awaitable(*this);
180 : }
181 : };
182 :
183 : } // namespace boost::corosio
184 :
185 : #endif
|