include/boost/corosio/io/io_signal_set.hpp

100.0% Lines (13 / 13) 100.0% Functions (7 / 7)
io_signal_set.hpp
f(x) Functions (7)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
11 #define BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14 #include <boost/corosio/detail/op_base.hpp>
15 #include <boost/corosio/io/io_object.hpp>
16 #include <boost/capy/results.hpp>
17 #include <boost/capy/error.hpp>
18 #include <boost/capy/ex/executor_ref.hpp>
19 #include <boost/capy/ex/await_context.hpp>
20
21 #include <boost/capy/continuation.hpp>
22
23 #include <coroutine>
24 #include <stop_token>
25 #include <system_error>
26
27 namespace boost::corosio {
28
29 /** Delivers a registered signal to the waiting coroutine.
30
31 Provides the common signal set interface: `wait` and `cancel`.
32 Concrete classes like @ref signal_set add signal registration
33 (add, remove, clear) and platform-specific flags.
34
35 @par Thread Safety
36 Distinct objects: Safe.
37 Shared objects: Unsafe.
38
39 @see signal_set, io_object
40 */
41 class BOOST_COROSIO_DECL io_signal_set : public io_object
42 {
43 struct wait_awaitable : detail::value_op_base<wait_awaitable, int>
44 {
45 private:
46 friend io_signal_set;
47 friend detail::value_op_base<wait_awaitable, int>;
48
49 io_signal_set& s_;
50
51 205889x explicit wait_awaitable(io_signal_set& s) noexcept : s_(s) {}
52
53 std::coroutine_handle<>
54 205842x dispatch(capy::continuation& cont, capy::executor_ref ex) const
55 {
56 205842x return s_.get().wait(cont, ex, token_, &ec_, &value_);
57 }
58 };
59
60 public:
61 /** Define backend hooks for signal set wait and cancel.
62
63 Platform backends derive from this to implement
64 signal delivery notification.
65 */
66 struct implementation : io_object::implementation
67 {
68 /** Initiate an asynchronous wait for a signal.
69
70 @param cont Continuation to resume on completion; it lives in
71 the awaiting frame until then.
72 @param ex Executor for dispatching the completion.
73 @param token Stop token for cancellation.
74 @param ec Output error code.
75 @param signo Output signal number.
76
77 @return Coroutine handle to resume immediately.
78 */
79 virtual std::coroutine_handle<> wait(
80 capy::continuation& cont,
81 capy::executor_ref ex,
82 std::stop_token token,
83 std::error_code* ec,
84 int* signo) = 0;
85
86 /** Cancel all pending wait operations.
87
88 Cancelled waiters complete with an error that
89 compares equal to `capy::cond::canceled`.
90 */
91 virtual void cancel() noexcept = 0;
92 };
93
94 /** Cancel all operations associated with the signal set.
95
96 Forces the completion of any pending asynchronous wait
97 operations. Each cancelled operation completes with an error
98 code that compares equal to `capy::cond::canceled`.
99
100 Cancellation does not alter the set of registered signals.
101 */
102 200021x void cancel() noexcept
103 {
104 200021x do_cancel();
105 200021x }
106
107 /** Wait for a signal to be delivered.
108
109 The operation supports cancellation via `std::stop_token` through
110 the affine awaitable protocol. If the associated stop token is
111 triggered, the operation completes immediately with an error
112 that compares equal to `capy::cond::canceled`.
113
114 This signal set must outlive the returned awaitable.
115
116 @return An awaitable that completes with `results<int>`.
117 Returns the signal number when a signal is delivered,
118 or an error code on failure.
119 */
120 205889x [[nodiscard]] auto wait()
121 {
122 205889x return wait_awaitable(*this);
123 }
124
125 protected:
126 /** Dispatch cancel to the concrete implementation. */
127 virtual void do_cancel() noexcept = 0;
128
129 /** Adopt an existing handle.
130
131 @param h The handle the signal set takes ownership of.
132 */
133 3478x explicit io_signal_set(handle h) noexcept : io_object(std::move(h)) {}
134
135 /// Move construct.
136 4x io_signal_set(io_signal_set&& other) noexcept : io_object(std::move(other))
137 {
138 4x }
139
140 /// Move assign.
141 io_signal_set& operator=(io_signal_set&& other) noexcept
142 {
143 if (this != &other)
144 h_ = std::move(other.h_);
145 return *this;
146 }
147
148 /// Copy construction is disabled; the handle is uniquely owned.
149 io_signal_set(io_signal_set const&) = delete;
150 /// Copy assignment is disabled; the handle is uniquely owned.
151 io_signal_set& operator=(io_signal_set const&) = delete;
152
153 private:
154 205842x implementation& get() const noexcept
155 {
156 205842x return *static_cast<implementation*>(h_.get());
157 }
158 };
159
160 } // namespace boost::corosio
161
162 #endif
163