include/boost/corosio/native/detail/iocp/win_signal.hpp

100.0% Lines (3/3) 100.0% List of functions (1/1) -% Branches (0/0)
win_signal.hpp
f(x) Functions (1)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 Steve Gerbino
4 // Copyright (c) 2026 Michael Vandeberg
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See accompanying
7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // Official repository: https://github.com/cppalliance/corosio
10 //
11
12 #ifndef BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_SIGNAL_HPP
13 #define BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_SIGNAL_HPP
14
15 #include <boost/corosio/detail/platform.hpp>
16
17 #if BOOST_COROSIO_HAS_IOCP
18
19 #include <boost/corosio/detail/config.hpp>
20 #include <boost/corosio/signal_set.hpp>
21 #include <boost/corosio/detail/intrusive.hpp>
22 #include <boost/corosio/detail/scheduler_op.hpp>
23 #include <boost/capy/continuation.hpp>
24 #include <boost/capy/ex/executor_ref.hpp>
25
26 #include <coroutine>
27 #include <cstddef>
28 #include <cstdint>
29 #include <optional>
30 #include <stop_token>
31 #include <system_error>
32
33 namespace boost::corosio::detail {
34
35 // Forward declarations
36 class win_signals;
37 class win_signal;
38
39 // Maximum signal number supported
40 enum
41 {
42 max_signal_number = 32
43 };
44
45 /** Signal wait operation state. */
46 struct signal_op : scheduler_op
47 {
48 std::coroutine_handle<> h;
49 capy::continuation cont;
50 capy::executor_ref d;
51 std::error_code* ec_out = nullptr;
52 int* signal_out = nullptr;
53 int signal_number = 0;
54 signal_op* next_in_queue = nullptr;
55 win_signals* svc = nullptr;
56
57 static void do_complete(
58 void* owner,
59 scheduler_op* base,
60 std::uint32_t bytes,
61 std::uint32_t error);
62
63 signal_op() noexcept;
64 };
65
66 /** Per-signal registration tracking. */
67 struct signal_registration
68 {
69 int signal_number = 0;
70 win_signal* owner = nullptr;
71 std::size_t undelivered = 0;
72 signal_registration* next_in_table = nullptr;
73 signal_registration* prev_in_table = nullptr;
74 signal_registration* next_in_set = nullptr;
75 };
76
77 /** Signal set implementation for Windows.
78
79 This class contains the state for a single signal_set, including
80 registered signals and pending wait operation.
81
82 @note Internal implementation detail. Users interact with signal_set class.
83 */
84 class win_signal final
85 : public signal_set::implementation
86 , public intrusive_list<win_signal>::node
87 {
88 friend class win_signals;
89
90 win_signals& svc_;
91 signal_registration* signals_ = nullptr;
92 signal_op pending_op_;
93 bool waiting_ = false;
94 bool cancelled_ = false;
95
96 /** Routes a stop request into the service's per-operation cancel.
97
98 Deliberately NOT `cancel_wait`: that sets the sticky `cancelled_`
99 latch, which belongs to `cancel()` and scopes to the whole set. A
100 stop token scopes to one wait, so a late fire must be a no-op.
101 */
102 struct token_canceller
103 {
104 win_signal* self;
105 void operator()() const noexcept;
106 };
107
108 /** Armed for the duration of one wait; see wait().
109
110 Never reset while the service's mutex is held: ~stop_callback
111 blocks until a concurrently running callback returns, and that
112 callback takes the same mutex.
113 */
114 std::optional<std::stop_callback<token_canceller>> stop_cb_;
115
116 /** Set when a stop request arrives for the current wait.
117
118 Closes the same lost-wakeup race Task 2 documents: the callback is
119 armed before `start_wait` takes the lock, so a request landing in
120 that window would otherwise be dropped and the wait would park
121 forever. Distinct from the sticky per-set `cancelled_`.
122 */
123 bool token_cancelled_ = false;
124
125 public:
126 explicit win_signal(win_signals& svc) noexcept;
127
128 std::coroutine_handle<> wait(
129 std::coroutine_handle<>,
130 capy::executor_ref,
131 std::stop_token,
132 std::error_code*,
133 int*) override;
134
135 std::error_code add(int signal_number, signal_set::flags_t flags) override;
136 std::error_code remove(int signal_number) override;
137 std::error_code clear() override;
138 void cancel() noexcept override;
139
140 /// Disarm the wait's stop callback. Called before teardown.
141 79x void disarm_stop() noexcept
142 {
143 79x stop_cb_.reset();
144 79x }
145 };
146
147 } // namespace boost::corosio::detail
148
149 #endif // BOOST_COROSIO_HAS_IOCP
150
151 #endif // BOOST_COROSIO_NATIVE_DETAIL_IOCP_WIN_SIGNAL_HPP
152