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