TLA Line data 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_NATIVE_NATIVE_SIGNAL_SET_HPP
11 : #define BOOST_COROSIO_NATIVE_NATIVE_SIGNAL_SET_HPP
12 :
13 : #include <boost/corosio/signal_set.hpp>
14 : #include <boost/corosio/backend.hpp>
15 : #include <boost/corosio/detail/op_base.hpp>
16 :
17 : #ifndef BOOST_COROSIO_MRDOCS
18 : #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
19 : BOOST_COROSIO_HAS_KQUEUE
20 : #include <boost/corosio/native/detail/posix/posix_signal_service.hpp>
21 : #endif
22 :
23 : #if BOOST_COROSIO_HAS_IOCP
24 : #include <boost/corosio/native/detail/iocp/win_signals.hpp>
25 : #endif
26 : #endif // !BOOST_COROSIO_MRDOCS
27 :
28 : namespace boost::corosio {
29 :
30 : /** An asynchronous signal set with devirtualized wait operations.
31 :
32 : This class template inherits from @ref signal_set and shadows
33 : the `wait` operation with a version that calls the backend
34 : implementation directly, allowing the compiler to inline
35 : through the entire call chain.
36 :
37 : Non-async operations (`add`, `remove`, `clear`, `cancel`)
38 : remain unchanged and dispatch through the compiled library.
39 :
40 : A `native_signal_set` IS-A `signal_set` and can be passed to
41 : any function expecting `signal_set&`.
42 :
43 : @tparam Backend A backend tag value (e.g., `epoll`).
44 :
45 : @par Thread Safety
46 : Same as @ref signal_set.
47 :
48 : @see signal_set, epoll_t, iocp_t
49 : */
50 : template<auto Backend>
51 : class native_signal_set : public signal_set
52 : {
53 : using backend_type = decltype(Backend);
54 : using impl_type = typename backend_type::signal_type;
55 :
56 : impl_type& get_impl() noexcept
57 : {
58 : return *static_cast<impl_type*>(h_.get());
59 : }
60 :
61 : struct native_wait_awaitable
62 : : detail::value_op_base<native_wait_awaitable, int>
63 : {
64 : native_signal_set& self_;
65 :
66 : explicit native_wait_awaitable(native_signal_set& self) noexcept
67 : : self_(self)
68 : {
69 : }
70 :
71 : std::coroutine_handle<>
72 : dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
73 : {
74 : return self_.get_impl().wait(
75 : h, ex, this->token_, &this->ec_, &this->value_);
76 : }
77 : };
78 :
79 : public:
80 : /** Construct a native signal set from an execution context.
81 :
82 : @param ctx The execution context that will own this signal set.
83 : */
84 HIT 2 : explicit native_signal_set(capy::execution_context& ctx) : signal_set(ctx)
85 : {
86 2 : }
87 :
88 : /** Construct a native signal set with initial signals.
89 :
90 : @param ctx The execution context that will own this signal set.
91 : @param signal First signal number to add.
92 : @param signals Additional signal numbers to add.
93 :
94 : @throws std::system_error on failure.
95 :
96 : @see add for the non-throwing form: construct with the
97 : context alone, then `add()` each signal.
98 : */
99 : template<std::convertible_to<int>... Signals>
100 4 : native_signal_set(
101 : capy::execution_context& ctx, int signal, Signals... signals)
102 4 : : signal_set(ctx, signal, signals...)
103 : {
104 4 : }
105 :
106 : /** Move construct.
107 :
108 : @param other The signal set to move from.
109 :
110 : @pre No awaitables returned by @p other's methods exist.
111 : @pre The execution context associated with @p other must
112 : outlive this signal set.
113 : */
114 : native_signal_set(native_signal_set&&) noexcept = default;
115 :
116 : /** Move assign.
117 :
118 : @param other The signal set to move from.
119 :
120 : @pre No awaitables returned by either `*this` or @p other's
121 : methods exist.
122 : @pre The execution context associated with @p other must
123 : outlive this signal set.
124 : */
125 : native_signal_set& operator=(native_signal_set&&) noexcept = default;
126 :
127 : native_signal_set(native_signal_set const&) = delete;
128 : native_signal_set& operator=(native_signal_set const&) = delete;
129 :
130 : /** Wait for a signal to be delivered.
131 :
132 : Calls the backend implementation directly, bypassing virtual
133 : dispatch. Otherwise identical to @ref signal_set::wait.
134 :
135 : @return An awaitable yielding `io_result<int>`.
136 :
137 : This signal set must outlive the returned awaitable.
138 : */
139 : [[nodiscard]] auto wait()
140 : {
141 : return native_wait_awaitable(*this);
142 : }
143 : };
144 :
145 : } // namespace boost::corosio
146 :
147 : #endif
|