TLA Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
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_DETAIL_SCHEDULER_HPP
13 : #define BOOST_COROSIO_DETAIL_SCHEDULER_HPP
14 :
15 : #include <boost/corosio/detail/config.hpp>
16 : #include <boost/capy/continuation.hpp>
17 : #include <coroutine>
18 :
19 : #include <cstddef>
20 :
21 : namespace boost::corosio::detail {
22 :
23 : class scheduler_op;
24 :
25 : /** Define the abstract interface for the event loop scheduler.
26 :
27 : Concrete backends (epoll, IOCP, kqueue, select) derive from
28 : this to implement the reactor/proactor event loop. The
29 : @ref io_context delegates all scheduling operations here.
30 :
31 : @see io_context
32 : */
33 : struct BOOST_COROSIO_DECL scheduler
34 : {
35 HIT 1225 : virtual ~scheduler() = default;
36 :
37 : /// Post a coroutine handle for deferred execution.
38 : virtual void post(std::coroutine_handle<>) const = 0;
39 :
40 : /// Post a scheduler operation for deferred execution.
41 : virtual void post(scheduler_op*) const = 0;
42 :
43 : /// Post a continuation for deferred execution (zero-allocation).
44 : virtual void post(capy::continuation&) const = 0;
45 :
46 : /// Increment the outstanding work count.
47 : virtual void work_started() noexcept = 0;
48 :
49 : /// Decrement the outstanding work count.
50 : virtual void work_finished() noexcept = 0;
51 :
52 : /// Check if the calling thread is running the event loop.
53 : virtual bool running_in_this_thread() const noexcept = 0;
54 :
55 : /// Signal the event loop to stop.
56 : virtual void stop() = 0;
57 :
58 : /// Check if the event loop has been stopped.
59 : virtual bool stopped() const noexcept = 0;
60 :
61 : /// Reset the stopped state so `run()` can be called again.
62 : virtual void restart() = 0;
63 :
64 : /// Run the event loop, blocking until all work completes.
65 : virtual std::size_t run() = 0;
66 :
67 : /// Run one handler, blocking until one completes.
68 : virtual std::size_t run_one() = 0;
69 :
70 : /** Run one handler, blocking up to @p usec microseconds.
71 :
72 : @param usec Maximum wait time in microseconds.
73 :
74 : @return The number of handlers executed (0 or 1).
75 : */
76 : virtual std::size_t wait_one(long usec) = 0;
77 :
78 : /// Run all ready handlers without blocking.
79 : virtual std::size_t poll() = 0;
80 :
81 : /// Run at most one ready handler without blocking.
82 : virtual std::size_t poll_one() = 0;
83 :
84 : /** Register the read end of the POSIX signal self-pipe.
85 :
86 : Called once (by the first signal_set to register a signal) so the
87 : backend's event loop watches @p read_fd for readability. When the
88 : pipe becomes readable the backend drains it and calls
89 : `posix_signal_service::deliver_signal` for each pending signal, in
90 : normal thread context. This keeps the C signal handler
91 : async-signal-safe: it only writes the signal number to the pipe.
92 :
93 : POSIX backends override this; the default is a no-op (Windows/IOCP
94 : uses synchronous C-runtime signal handling instead).
95 :
96 : @param read_fd The read end of the global signal self-pipe.
97 : */
98 MIS 0 : virtual void register_signal_reader(int read_fd) { (void)read_fd; }
99 :
100 : /// Decomposed threading configuration applied via @ref configure_threading.
101 : struct threading_config
102 : {
103 : /// Scheduler mutex/condvar enabled. Off only in the `unsafe` tier.
104 : bool scheduler_locking = true;
105 : /// Per-descriptor (reactor) or ring (io_uring) I/O lock enabled.
106 : /// Off in the `unsafe_io` and `unsafe` tiers.
107 : bool reactor_io_locking = true;
108 : /// A single run thread is guaranteed (a lockless tier): elide
109 : /// inter-run-thread wakeups.
110 : bool one_thread = false;
111 : };
112 :
113 : /// True in the fully-lockless (`unsafe`) tier. The resolver and POSIX
114 : /// file services gate their `operation_not_supported` result on this.
115 0 : virtual bool scheduler_locking_disabled() const noexcept { return false; }
116 :
117 : /// Apply @ref threading_config. Default no-op.
118 0 : virtual void configure_threading(threading_config) noexcept {}
119 : };
120 :
121 : } // namespace boost::corosio::detail
122 :
123 : #endif
|