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