100.00% Lines (13/13) 100.00% Functions (7/7)
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   // Copyright (c) 2026 Michael Vandeberg
4   // 4   //
5   // Distributed under the Boost Software License, Version 1.0. (See accompanying 5   // 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) 6   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7   // 7   //
8   // Official repository: https://github.com/cppalliance/corosio 8   // Official repository: https://github.com/cppalliance/corosio
9   // 9   //
10   10  
11   #ifndef BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP 11   #ifndef BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
12   #define BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP 12   #define BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
13   13  
14   #include <boost/corosio/detail/config.hpp> 14   #include <boost/corosio/detail/config.hpp>
15   #include <boost/corosio/detail/op_base.hpp> 15   #include <boost/corosio/detail/op_base.hpp>
16   #include <boost/corosio/io/io_object.hpp> 16   #include <boost/corosio/io/io_object.hpp>
17   #include <boost/capy/results.hpp> 17   #include <boost/capy/results.hpp>
18   #include <boost/capy/error.hpp> 18   #include <boost/capy/error.hpp>
19   #include <boost/capy/ex/executor_ref.hpp> 19   #include <boost/capy/ex/executor_ref.hpp>
20   #include <boost/capy/ex/await_context.hpp> 20   #include <boost/capy/ex/await_context.hpp>
21   21  
22   #include <boost/capy/continuation.hpp> 22   #include <boost/capy/continuation.hpp>
23   23  
24   #include <coroutine> 24   #include <coroutine>
25   #include <stop_token> 25   #include <stop_token>
26   #include <system_error> 26   #include <system_error>
27   27  
28   namespace boost::corosio { 28   namespace boost::corosio {
29   29  
30   /** Delivers a registered signal to the waiting coroutine. 30   /** Delivers a registered signal to the waiting coroutine.
31   31  
32   Provides the common signal set interface: `wait` and `cancel`. 32   Provides the common signal set interface: `wait` and `cancel`.
33   Concrete classes like @ref signal_set add signal registration 33   Concrete classes like @ref signal_set add signal registration
34   (add, remove, clear) and platform-specific flags. 34   (add, remove, clear) and platform-specific flags.
35   35  
36   @par Thread Safety 36   @par Thread Safety
37   Distinct objects: Safe. 37   Distinct objects: Safe.
38   Shared objects: Unsafe. 38   Shared objects: Unsafe.
39   39  
40   @see @ref signal_set, @ref io_object 40   @see @ref signal_set, @ref io_object
41   */ 41   */
42   class BOOST_COROSIO_DECL io_signal_set : public io_object 42   class BOOST_COROSIO_DECL io_signal_set : public io_object
43   { 43   {
44   struct wait_awaitable : detail::value_op_base<wait_awaitable, int> 44   struct wait_awaitable : detail::value_op_base<wait_awaitable, int>
45   { 45   {
46   private: 46   private:
47   friend io_signal_set; 47   friend io_signal_set;
48   friend detail::value_op_base<wait_awaitable, int>; 48   friend detail::value_op_base<wait_awaitable, int>;
49   49  
50   io_signal_set& s_; 50   io_signal_set& s_;
51   51  
HITCBC 52   206064 explicit wait_awaitable(io_signal_set& s) noexcept : s_(s) {} 52   205875 explicit wait_awaitable(io_signal_set& s) noexcept : s_(s) {}
53   53  
54   std::coroutine_handle<> 54   std::coroutine_handle<>
HITCBC 55   206042 dispatch(capy::continuation& cont, capy::executor_ref ex) const 55   205838 dispatch(capy::continuation& cont, capy::executor_ref ex) const
56   { 56   {
HITCBC 57   206042 return s_.get().wait(cont, ex, token_, &ec_, &value_); 57   205838 return s_.get().wait(cont, ex, token_, &ec_, &value_);
58   } 58   }
59   }; 59   };
60   60  
61   public: 61   public:
62   /** Define backend hooks for signal set wait and cancel. 62   /** Define backend hooks for signal set wait and cancel.
63   63  
64   Platform backends derive from this to implement 64   Platform backends derive from this to implement
65   signal delivery notification. 65   signal delivery notification.
66   */ 66   */
67   struct implementation : io_object::implementation 67   struct implementation : io_object::implementation
68   { 68   {
69   /** Initiate an asynchronous wait for a signal. 69   /** Initiate an asynchronous wait for a signal.
70   70  
71   @param cont Continuation to resume on completion; it lives in 71   @param cont Continuation to resume on completion; it lives in
72   the awaiting frame until then. 72   the awaiting frame until then.
73   @param ex Executor for dispatching the completion. 73   @param ex Executor for dispatching the completion.
74   @param token Stop token for cancellation. 74   @param token Stop token for cancellation.
75   @param ec Output error code. 75   @param ec Output error code.
76   @param signo Output signal number. 76   @param signo Output signal number.
77   77  
78   @return Coroutine handle to resume immediately. 78   @return Coroutine handle to resume immediately.
79   */ 79   */
80   virtual std::coroutine_handle<> wait( 80   virtual std::coroutine_handle<> wait(
81   capy::continuation& cont, 81   capy::continuation& cont,
82   capy::executor_ref ex, 82   capy::executor_ref ex,
83   std::stop_token token, 83   std::stop_token token,
84   std::error_code* ec, 84   std::error_code* ec,
85   int* signo) = 0; 85   int* signo) = 0;
86   86  
87   /** Cancel all pending wait operations. 87   /** Cancel all pending wait operations.
88   88  
89   Cancelled waiters complete with an error that 89   Cancelled waiters complete with an error that
90   compares equal to `capy::cond::canceled`. 90   compares equal to `capy::cond::canceled`.
91   */ 91   */
92   virtual void cancel() noexcept = 0; 92   virtual void cancel() noexcept = 0;
93   }; 93   };
94   94  
95   /** Cancel all operations associated with the signal set. 95   /** Cancel all operations associated with the signal set.
96   96  
97   Forces the completion of any pending asynchronous wait 97   Forces the completion of any pending asynchronous wait
98   operations. Each cancelled operation completes with an error 98   operations. Each cancelled operation completes with an error
99   code that compares equal to `capy::cond::canceled`. 99   code that compares equal to `capy::cond::canceled`.
100   100  
101   Cancellation does not alter the set of registered signals. 101   Cancellation does not alter the set of registered signals.
102   */ 102   */
HITCBC 103   200021 void cancel() noexcept 103   200021 void cancel() noexcept
104   { 104   {
HITCBC 105   200021 do_cancel(); 105   200021 do_cancel();
HITCBC 106   200021 } 106   200021 }
107   107  
108   /** Wait for a signal to be delivered. 108   /** Wait for a signal to be delivered.
109   109  
110   The operation supports cancellation via `std::stop_token` through 110   The operation supports cancellation via `std::stop_token` through
111   the affine awaitable protocol. If the associated stop token is 111   the affine awaitable protocol. If the associated stop token is
112   triggered, the operation completes immediately with an error 112   triggered, the operation completes immediately with an error
113   that compares equal to `capy::cond::canceled`. 113   that compares equal to `capy::cond::canceled`.
114   114  
115   This signal set must outlive the returned awaitable. 115   This signal set must outlive the returned awaitable.
116   116  
117   @return An awaitable that completes with `results<int>`. 117   @return An awaitable that completes with `results<int>`.
118   Returns the signal number when a signal is delivered, 118   Returns the signal number when a signal is delivered,
119   or an error code on failure. 119   or an error code on failure.
120   */ 120   */
HITCBC 121   206064 [[nodiscard]] auto wait() 121   205875 [[nodiscard]] auto wait()
122   { 122   {
HITCBC 123   206064 return wait_awaitable(*this); 123   205875 return wait_awaitable(*this);
124   } 124   }
125   125  
126   protected: 126   protected:
127   /** Dispatch cancel to the concrete implementation. */ 127   /** Dispatch cancel to the concrete implementation. */
128   virtual void do_cancel() noexcept = 0; 128   virtual void do_cancel() noexcept = 0;
129   129  
130   /** Adopt an existing handle. 130   /** Adopt an existing handle.
131   131  
132   @param h The handle the signal set takes ownership of. 132   @param h The handle the signal set takes ownership of.
133   */ 133   */
HITCBC 134   3486 explicit io_signal_set(handle h) noexcept : io_object(std::move(h)) {} 134   3486 explicit io_signal_set(handle h) noexcept : io_object(std::move(h)) {}
135   135  
136   /// Move construct. 136   /// Move construct.
HITCBC 137   6 io_signal_set(io_signal_set&& other) noexcept : io_object(std::move(other)) 137   6 io_signal_set(io_signal_set&& other) noexcept : io_object(std::move(other))
138   { 138   {
HITCBC 139   6 } 139   6 }
140   140  
141   /// Move assign. 141   /// Move assign.
142   io_signal_set& operator=(io_signal_set&& other) noexcept 142   io_signal_set& operator=(io_signal_set&& other) noexcept
143   { 143   {
144   if (this != &other) 144   if (this != &other)
145   h_ = std::move(other.h_); 145   h_ = std::move(other.h_);
146   return *this; 146   return *this;
147   } 147   }
148   148  
149   /// Copy construction is disabled; the handle is uniquely owned. 149   /// Copy construction is disabled; the handle is uniquely owned.
150   io_signal_set(io_signal_set const&) = delete; 150   io_signal_set(io_signal_set const&) = delete;
151   /// Copy assignment is disabled; the handle is uniquely owned. 151   /// Copy assignment is disabled; the handle is uniquely owned.
152   io_signal_set& operator=(io_signal_set const&) = delete; 152   io_signal_set& operator=(io_signal_set const&) = delete;
153   153  
154   private: 154   private:
HITCBC 155   206042 implementation& get() const noexcept 155   205838 implementation& get() const noexcept
156   { 156   {
HITCBC 157   206042 return *static_cast<implementation*>(h_.get()); 157   205838 return *static_cast<implementation*>(h_.get());
158   } 158   }
159   }; 159   };
160   160  
161   } // namespace boost::corosio 161   } // namespace boost::corosio
162   162  
163   #endif 163   #endif