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