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