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