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 : /** Waits for a registered signal, calling the backend directly.
31 :
32 : This class template inherits from @ref signal_set. It shadows the
33 : `wait` operation with a version that calls the backend
34 : implementation directly. The compiler can then inline through the
35 : 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 owns 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 owns 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 : @pre No awaitables returned by the source's methods exist.
109 : @pre The execution context associated with the source must
110 : outlive this signal set.
111 : */
112 : native_signal_set(native_signal_set&&) noexcept = default;
113 :
114 : /** Move assign.
115 :
116 : @pre No awaitables returned by either `*this` or the source's
117 : methods exist.
118 : @pre The execution context associated with the source must
119 : outlive this signal set.
120 : */
121 : native_signal_set& operator=(native_signal_set&&) noexcept = default;
122 :
123 : /// Copy construction is disabled; the handle is uniquely owned.
124 : native_signal_set(native_signal_set const&) = delete;
125 : /// Copy assignment is disabled; the handle is uniquely owned.
126 : native_signal_set& operator=(native_signal_set const&) = delete;
127 :
128 : /** Wait for a signal to be delivered.
129 :
130 : Calls the backend implementation directly, bypassing virtual
131 : dispatch. Otherwise identical to @ref signal_set::wait.
132 :
133 : @return An awaitable yielding `io_result<int>`.
134 :
135 : This signal set must outlive the returned awaitable.
136 : */
137 : [[nodiscard]] auto wait()
138 : {
139 : return native_wait_awaitable(*this);
140 : }
141 : };
142 :
143 : } // namespace boost::corosio
144 :
145 : #endif
|