95.24% Lines (20/21) 100.00% Functions (9/9)
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_IO_IO_SIGNAL_SET_HPP 10   #ifndef BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
11   #define BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP 11   #define BOOST_COROSIO_IO_IO_SIGNAL_SET_HPP
12   12  
13   #include <boost/corosio/detail/config.hpp> 13   #include <boost/corosio/detail/config.hpp>
14   #include <boost/corosio/io/io_object.hpp> 14   #include <boost/corosio/io/io_object.hpp>
15   #include <boost/capy/io_result.hpp> 15   #include <boost/capy/io_result.hpp>
16   #include <boost/capy/error.hpp> 16   #include <boost/capy/error.hpp>
17   #include <boost/capy/ex/executor_ref.hpp> 17   #include <boost/capy/ex/executor_ref.hpp>
18   #include <boost/capy/ex/io_env.hpp> 18   #include <boost/capy/ex/io_env.hpp>
19   19  
20   #include <coroutine> 20   #include <coroutine>
21   #include <stop_token> 21   #include <stop_token>
22   #include <system_error> 22   #include <system_error>
23   23  
24   namespace boost::corosio { 24   namespace boost::corosio {
25   25  
26   /** Abstract base for asynchronous signal sets. 26   /** Abstract base for asynchronous signal sets.
27   27  
28   Provides the common signal set interface: `wait` and `cancel`. 28   Provides the common signal set interface: `wait` and `cancel`.
29   Concrete classes like @ref signal_set add signal registration 29   Concrete classes like @ref signal_set add signal registration
30   (add, remove, clear) and platform-specific flags. 30   (add, remove, clear) and platform-specific flags.
31   31  
32   @par Thread Safety 32   @par Thread Safety
33   Distinct objects: Safe. 33   Distinct objects: Safe.
34   Shared objects: Unsafe. 34   Shared objects: Unsafe.
35   35  
36   @see signal_set, io_object 36   @see signal_set, io_object
37   */ 37   */
38   class BOOST_COROSIO_DECL io_signal_set : public io_object 38   class BOOST_COROSIO_DECL io_signal_set : public io_object
39   { 39   {
40   struct wait_awaitable 40   struct wait_awaitable
41   { 41   {
42   io_signal_set& s_; 42   io_signal_set& s_;
43   std::stop_token token_; 43   std::stop_token token_;
44   mutable std::error_code ec_; 44   mutable std::error_code ec_;
45   mutable int signal_number_ = 0; 45   mutable int signal_number_ = 0;
46   46  
HITCBC 47   28 explicit wait_awaitable(io_signal_set& s) noexcept : s_(s) {} 47   28 explicit wait_awaitable(io_signal_set& s) noexcept : s_(s) {}
48   48  
HITCBC 49   28 bool await_ready() const noexcept 49   28 bool await_ready() const noexcept
50   { 50   {
HITCBC 51   28 return token_.stop_requested(); 51   28 return token_.stop_requested();
52   } 52   }
53   53  
HITCBC 54   28 capy::io_result<int> await_resume() const noexcept 54   28 capy::io_result<int> await_resume() const noexcept
55   { 55   {
HITCBC 56   28 if (token_.stop_requested()) 56   28 if (token_.stop_requested())
MISUBC 57   return {capy::error::canceled, 0}; 57   return {capy::error::canceled, 0};
HITCBC 58   28 return {ec_, signal_number_}; 58   28 return {ec_, signal_number_};
59   } 59   }
60   60  
HITCBC 61   28 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env) 61   28 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
62   -> std::coroutine_handle<> 62   -> std::coroutine_handle<>
63   { 63   {
HITCBC 64   28 token_ = env->stop_token; 64   28 token_ = env->stop_token;
HITCBC 65   84 return s_.get().wait( 65   84 return s_.get().wait(
HITCBC 66   84 h, env->executor, token_, &ec_, &signal_number_); 66   84 h, env->executor, token_, &ec_, &signal_number_);
67   } 67   }
68   }; 68   };
69   69  
70   public: 70   public:
71   /** Define backend hooks for signal set wait and cancel. 71   /** Define backend hooks for signal set wait and cancel.
72   72  
73   Platform backends derive from this to implement 73   Platform backends derive from this to implement
74   signal delivery notification. 74   signal delivery notification.
75   */ 75   */
76   struct implementation : io_object::implementation 76   struct implementation : io_object::implementation
77   { 77   {
78   /** Initiate an asynchronous wait for a signal. 78   /** Initiate an asynchronous wait for a signal.
79   79  
80   @param h Coroutine handle to resume on completion. 80   @param h Coroutine handle to resume on completion.
81   @param ex Executor for dispatching the completion. 81   @param ex Executor for dispatching the completion.
82   @param token Stop token for cancellation. 82   @param token Stop token for cancellation.
83   @param ec Output error code. 83   @param ec Output error code.
84   @param signo Output signal number. 84   @param signo Output signal number.
85   85  
86   @return Coroutine handle to resume immediately. 86   @return Coroutine handle to resume immediately.
87   */ 87   */
88   virtual std::coroutine_handle<> wait( 88   virtual std::coroutine_handle<> wait(
89   std::coroutine_handle<> h, 89   std::coroutine_handle<> h,
90   capy::executor_ref ex, 90   capy::executor_ref ex,
91   std::stop_token token, 91   std::stop_token token,
92   std::error_code* ec, 92   std::error_code* ec,
93   int* signo) = 0; 93   int* signo) = 0;
94   94  
95   /** Cancel all pending wait operations. 95   /** Cancel all pending wait operations.
96   96  
97   Cancelled waiters complete with an error that 97   Cancelled waiters complete with an error that
98   compares equal to `capy::cond::canceled`. 98   compares equal to `capy::cond::canceled`.
99   */ 99   */
100   virtual void cancel() = 0; 100   virtual void cancel() = 0;
101   }; 101   };
102   102  
103   /** Cancel all operations associated with the signal set. 103   /** Cancel all operations associated with the signal set.
104   104  
105   Forces the completion of any pending asynchronous wait 105   Forces the completion of any pending asynchronous wait
106   operations. Each cancelled operation completes with an error 106   operations. Each cancelled operation completes with an error
107   code that compares equal to `capy::cond::canceled`. 107   code that compares equal to `capy::cond::canceled`.
108   108  
109   Cancellation does not alter the set of registered signals. 109   Cancellation does not alter the set of registered signals.
110   */ 110   */
HITCBC 111   14 void cancel() 111   14 void cancel()
112   { 112   {
HITCBC 113   14 do_cancel(); 113   14 do_cancel();
HITCBC 114   14 } 114   14 }
115   115  
116   /** Wait for a signal to be delivered. 116   /** Wait for a signal to be delivered.
117   117  
118   The operation supports cancellation via `std::stop_token` through 118   The operation supports cancellation via `std::stop_token` through
119   the affine awaitable protocol. If the associated stop token is 119   the affine awaitable protocol. If the associated stop token is
120   triggered, the operation completes immediately with an error 120   triggered, the operation completes immediately with an error
121   that compares equal to `capy::cond::canceled`. 121   that compares equal to `capy::cond::canceled`.
122   122  
123   This signal set must outlive the returned awaitable. 123   This signal set must outlive the returned awaitable.
124   124  
125   @return An awaitable that completes with `io_result<int>`. 125   @return An awaitable that completes with `io_result<int>`.
126   Returns the signal number when a signal is delivered, 126   Returns the signal number when a signal is delivered,
127   or an error code on failure. 127   or an error code on failure.
128   */ 128   */
HITCBC 129   28 auto wait() 129   28 auto wait()
130   { 130   {
HITCBC 131   28 return wait_awaitable(*this); 131   28 return wait_awaitable(*this);
132   } 132   }
133   133  
134   protected: 134   protected:
135   /** Dispatch cancel to the concrete implementation. */ 135   /** Dispatch cancel to the concrete implementation. */
136   virtual void do_cancel() = 0; 136   virtual void do_cancel() = 0;
137   137  
HITCBC 138   90 explicit io_signal_set(handle h) noexcept : io_object(std::move(h)) {} 138   90 explicit io_signal_set(handle h) noexcept : io_object(std::move(h)) {}
139   139  
140   /// Move construct. 140   /// Move construct.
HITCBC 141   2 io_signal_set(io_signal_set&& other) noexcept : io_object(std::move(other)) 141   2 io_signal_set(io_signal_set&& other) noexcept : io_object(std::move(other))
142   { 142   {
HITCBC 143   2 } 143   2 }
144   144  
145   /// Move assign. 145   /// Move assign.
146   io_signal_set& operator=(io_signal_set&& other) noexcept 146   io_signal_set& operator=(io_signal_set&& other) noexcept
147   { 147   {
148   if (this != &other) 148   if (this != &other)
149   h_ = std::move(other.h_); 149   h_ = std::move(other.h_);
150   return *this; 150   return *this;
151   } 151   }
152   152  
153   io_signal_set(io_signal_set const&) = delete; 153   io_signal_set(io_signal_set const&) = delete;
154   io_signal_set& operator=(io_signal_set const&) = delete; 154   io_signal_set& operator=(io_signal_set const&) = delete;
155   155  
156   private: 156   private:
HITCBC 157   28 implementation& get() const noexcept 157   28 implementation& get() const noexcept
158   { 158   {
HITCBC 159   28 return *static_cast<implementation*>(h_.get()); 159   28 return *static_cast<implementation*>(h_.get());
160   } 160   }
161   }; 161   };
162   162  
163   } // namespace boost::corosio 163   } // namespace boost::corosio
164   164  
165   #endif 165   #endif