TLA Line data Source code
1 : //
2 : // Copyright (c) 2026 Steve Gerbino
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_NATIVE_IO_CONTEXT_HPP
11 : #define BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
12 :
13 : #include <boost/corosio/io_context.hpp>
14 : #include <boost/corosio/backend.hpp>
15 :
16 : #ifndef BOOST_COROSIO_MRDOCS
17 : #if BOOST_COROSIO_HAS_EPOLL
18 : #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp>
19 : #endif
20 :
21 : #if BOOST_COROSIO_HAS_SELECT
22 : #include <boost/corosio/native/detail/select/select_scheduler.hpp>
23 : #endif
24 :
25 : #if BOOST_COROSIO_HAS_KQUEUE
26 : #include <boost/corosio/native/detail/kqueue/kqueue_scheduler.hpp>
27 : #endif
28 :
29 : #if BOOST_COROSIO_HAS_IOCP
30 : #include <boost/corosio/native/detail/iocp/win_scheduler.hpp>
31 : #endif
32 : #endif // !BOOST_COROSIO_MRDOCS
33 :
34 : namespace boost::corosio {
35 :
36 : /** An I/O context with devirtualized event loop methods.
37 :
38 : This class template inherits from @ref io_context and shadows
39 : all public methods with versions that call the concrete
40 : scheduler directly, bypassing virtual dispatch. No new state
41 : is added.
42 :
43 : A `native_io_context` IS-A `io_context` and can be passed
44 : anywhere an `io_context&` is accepted, in which case virtual
45 : dispatch is used transparently.
46 :
47 : @tparam Backend A backend tag value (e.g., `epoll`,
48 : `iocp`) whose type provides `scheduler_type`.
49 :
50 : @par Thread Safety
51 : Same as the underlying context type.
52 :
53 : @par Example
54 : @code
55 : #include <boost/corosio/native/native_io_context.hpp>
56 :
57 : native_io_context<epoll> ctx;
58 : ctx.poll(); // devirtualized call
59 : @endcode
60 :
61 : @see io_context, epoll_t, iocp_t
62 : */
63 : template<auto Backend>
64 : class native_io_context : public io_context
65 : {
66 : using backend_type = decltype(Backend);
67 : using scheduler_type = typename backend_type::scheduler_type;
68 :
69 HIT 36 : scheduler_type& sched() noexcept
70 : {
71 36 : return *static_cast<scheduler_type*>(this->sched_);
72 : }
73 :
74 : public:
75 : /** Construct with default concurrency. */
76 16 : native_io_context() : io_context(Backend) {}
77 :
78 : /** Construct with a concurrency hint.
79 :
80 : @param concurrency_hint Hint for the number of threads that
81 : will call `run()`.
82 : */
83 2 : explicit native_io_context(unsigned concurrency_hint)
84 2 : : io_context(Backend, concurrency_hint)
85 : {
86 2 : }
87 :
88 : /** Construct with runtime tuning options.
89 :
90 : @param opts Runtime options controlling scheduler and
91 : service behavior.
92 : @param concurrency_hint Hint for the number of threads that
93 : will call `run()`.
94 : */
95 2 : explicit native_io_context(
96 : io_context_options const& opts,
97 : unsigned concurrency_hint = std::thread::hardware_concurrency())
98 2 : : io_context(Backend, opts, concurrency_hint)
99 : {
100 2 : }
101 :
102 : // Non-copyable, non-movable
103 : native_io_context(native_io_context const&) = delete;
104 : native_io_context& operator=(native_io_context const&) = delete;
105 :
106 : /// Signal the context to stop processing.
107 2 : void stop()
108 : {
109 2 : sched().stop();
110 2 : }
111 :
112 : /// Return whether the context has been stopped.
113 18 : bool stopped() const noexcept
114 : {
115 18 : return const_cast<native_io_context*>(this)->sched().stopped();
116 : }
117 :
118 : /// Restart the context after being stopped.
119 2 : void restart()
120 : {
121 2 : sched().restart();
122 2 : }
123 :
124 : /** Process all pending work items.
125 :
126 : @return The number of handlers executed.
127 : */
128 2 : std::size_t run()
129 : {
130 2 : return sched().run();
131 : }
132 :
133 : /** Process at most one pending work item.
134 :
135 : @return The number of handlers executed (0 or 1).
136 : */
137 : std::size_t run_one()
138 : {
139 : return sched().run_one();
140 : }
141 :
142 : /** Process work items for the specified duration.
143 :
144 : @param rel_time The duration for which to process work.
145 :
146 : @return The number of handlers executed.
147 : */
148 : template<class Rep, class Period>
149 4 : std::size_t run_for(std::chrono::duration<Rep, Period> const& rel_time)
150 : {
151 4 : return run_until(std::chrono::steady_clock::now() + rel_time);
152 : }
153 :
154 : /** Process work items until the specified time.
155 :
156 : @param abs_time The time point until which to process work.
157 :
158 : @return The number of handlers executed.
159 : */
160 : template<class Clock, class Duration>
161 : std::size_t
162 4 : run_until(std::chrono::time_point<Clock, Duration> const& abs_time)
163 : {
164 4 : std::size_t n = 0;
165 6 : while (run_one_until(abs_time))
166 2 : if (n != (std::numeric_limits<std::size_t>::max)())
167 2 : ++n;
168 4 : return n;
169 : }
170 :
171 : /** Process at most one work item for the specified duration.
172 :
173 : @param rel_time The duration for which the call may block.
174 :
175 : @return The number of handlers executed (0 or 1).
176 : */
177 : template<class Rep, class Period>
178 : std::size_t run_one_for(std::chrono::duration<Rep, Period> const& rel_time)
179 : {
180 : return run_one_until(std::chrono::steady_clock::now() + rel_time);
181 : }
182 :
183 : /** Process at most one work item until the specified time.
184 :
185 : @param abs_time The time point until which the call may block.
186 :
187 : @return The number of handlers executed (0 or 1).
188 : */
189 : template<class Clock, class Duration>
190 : std::size_t
191 8 : run_one_until(std::chrono::time_point<Clock, Duration> const& abs_time)
192 : {
193 8 : typename Clock::time_point now = Clock::now();
194 12 : while (now < abs_time)
195 : {
196 10 : auto rel_time = abs_time - now;
197 10 : if (rel_time > std::chrono::seconds(1))
198 2 : rel_time = std::chrono::seconds(1);
199 :
200 20 : std::size_t s = sched().wait_one(
201 : static_cast<long>(
202 10 : std::chrono::duration_cast<std::chrono::microseconds>(
203 : rel_time)
204 10 : .count()));
205 :
206 10 : if (s || stopped())
207 6 : return s;
208 :
209 4 : now = Clock::now();
210 : }
211 2 : return 0;
212 : }
213 :
214 : /** Process all ready work items without blocking.
215 :
216 : @return The number of handlers executed.
217 : */
218 2 : std::size_t poll()
219 : {
220 2 : return sched().poll();
221 : }
222 :
223 : /** Process at most one ready work item without blocking.
224 :
225 : @return The number of handlers executed (0 or 1).
226 : */
227 : std::size_t poll_one()
228 : {
229 : return sched().poll_one();
230 : }
231 : };
232 :
233 : } // namespace boost::corosio
234 :
235 : #endif // BOOST_COROSIO_NATIVE_NATIVE_IO_CONTEXT_HPP
|