include/boost/corosio/native/native_signal_set.hpp

100.0% Lines (5 / 5) 100.0% Functions (4 / 4)
native_signal_set.hpp
f(x) Functions (4)
Line TLA Hits 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 2x explicit native_signal_set(capy::execution_context& ctx) : signal_set(ctx)
86 {
87 2x }
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 4x native_signal_set(
104 capy::execution_context& ctx, int signal, Signals... signals)
105 4x : signal_set(ctx, signal, signals...)
106 {
107 4x }
108
109 /** Move construct.
110
111 @pre No awaitables returned by the source's methods exist.
112 @pre The execution context associated with the source must
113 outlive this signal set.
114 */
115 native_signal_set(native_signal_set&&) noexcept = default;
116
117 /** Move assign.
118
119 @pre No awaitables returned by either `*this` or the source's
120 methods exist.
121 @pre The execution context associated with the source must
122 outlive this signal set.
123 */
124 native_signal_set& operator=(native_signal_set&&) noexcept = default;
125
126 /// Copy construction is disabled; the handle is uniquely owned.
127 native_signal_set(native_signal_set const&) = delete;
128 /// Copy assignment is disabled; the handle is uniquely owned.
129 native_signal_set& operator=(native_signal_set const&) = delete;
130
131 /** Wait for a signal to be delivered.
132
133 Calls the backend implementation directly, bypassing virtual
134 dispatch. Otherwise identical to @ref signal_set::wait.
135
136 @return An awaitable yielding `results<int>`.
137
138 This signal set must outlive the returned awaitable.
139 */
140 [[nodiscard]] auto wait()
141 {
142 return native_wait_awaitable(*this);
143 }
144 };
145
146 } // namespace boost::corosio
147
148 #endif
149