include/boost/corosio/native/detail/reactor/reactor_signal_pipe.hpp

100.0% Lines (7/7) 100.0% List of functions (2/2)
reactor_signal_pipe.hpp
f(x) Functions (2)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
3 //
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)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SIGNAL_PIPE_HPP
11 #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SIGNAL_PIPE_HPP
12
13 #include <boost/corosio/detail/platform.hpp>
14
15 #if BOOST_COROSIO_POSIX
16
17 #include <boost/corosio/native/detail/posix/posix_signal_service.hpp>
18 #include <boost/corosio/native/detail/reactor/reactor_descriptor_state.hpp>
19 #include <boost/corosio/native/detail/reactor/reactor_op_base.hpp>
20
21 #include <errno.h>
22
23 /*
24 Reactor signal-pipe reader
25 ==========================
26
27 Bridges the global POSIX signal self-pipe (see posix_signal_service.hpp)
28 to the reactor backends (epoll/kqueue/select). The concrete scheduler owns
29 one of these for its lifetime and, in register_signal_reader(), parks the
30 drain op as the descriptor's read_op then calls register_descriptor().
31
32 The drain op never completes: on each read-readiness edge, invoke_deferred_io
33 calls perform_io(), which drains the pipe and delivers the pending signals,
34 then reports EAGAIN so the op stays parked and re-fires on the next edge —
35 exactly the path a socket read op takes when the kernel has no more data.
36 Because deliver_signal() runs here, in normal dispatch context (not in the
37 signal handler and not under the reactor poll lock), its mutex locking is
38 safe.
39 */
40
41 namespace boost::corosio::detail {
42
43 struct reactor_signal_pipe_reader
44 {
45 // Parked read op: drains the self-pipe and re-arms via EAGAIN.
46 struct drain_op final : reactor_op_base
47 {
48 300x void perform_io() noexcept override
49 {
50 300x posix_signal_detail::drain_signal_pipe();
51 // Stay parked: EAGAIN tells invoke_deferred_io to keep this op
52 // installed as read_op and re-run it on the next readiness edge.
53 300x errn = EAGAIN;
54 300x }
55 };
56
57 reactor_descriptor_state desc;
58 drain_op op;
59
60 // Park the drain op and return the descriptor to hand to
61 // scheduler::register_descriptor(read_fd, ...).
62 82x reactor_descriptor_state* arm() noexcept
63 {
64 82x desc.read_op = &op;
65 82x return &desc;
66 }
67 };
68
69 } // namespace boost::corosio::detail
70
71 #endif // BOOST_COROSIO_POSIX
72
73 #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_SIGNAL_PIPE_HPP
74