src/corosio/src/io_context.cpp

47.1% Lines (24/51) 54.5% List of functions (6/11)
io_context.cpp
f(x) Functions (11)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #include <boost/corosio/io_context.hpp>
12 #include <boost/corosio/backend.hpp>
13 #include <boost/corosio/detail/thread_pool.hpp>
14
15 #include <thread>
16
17 #if BOOST_COROSIO_HAS_EPOLL
18 #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp>
19 #include <boost/corosio/native/detail/epoll/epoll_tcp_service.hpp>
20 #include <boost/corosio/native/detail/epoll/epoll_tcp_acceptor_service.hpp>
21 #include <boost/corosio/native/detail/epoll/epoll_udp_service.hpp>
22 #endif
23
24 #if BOOST_COROSIO_HAS_SELECT
25 #include <boost/corosio/native/detail/select/select_scheduler.hpp>
26 #include <boost/corosio/native/detail/select/select_tcp_service.hpp>
27 #include <boost/corosio/native/detail/select/select_tcp_acceptor_service.hpp>
28 #include <boost/corosio/native/detail/select/select_udp_service.hpp>
29 #endif
30
31 #if BOOST_COROSIO_HAS_KQUEUE
32 #include <boost/corosio/native/detail/kqueue/kqueue_scheduler.hpp>
33 #include <boost/corosio/native/detail/kqueue/kqueue_tcp_service.hpp>
34 #include <boost/corosio/native/detail/kqueue/kqueue_tcp_acceptor_service.hpp>
35 #include <boost/corosio/native/detail/kqueue/kqueue_udp_service.hpp>
36 #endif
37
38 #if BOOST_COROSIO_HAS_IOCP
39 #include <boost/corosio/native/detail/iocp/win_scheduler.hpp>
40 #include <boost/corosio/native/detail/iocp/win_tcp_acceptor_service.hpp>
41 #include <boost/corosio/native/detail/iocp/win_udp_service.hpp>
42 #include <boost/corosio/native/detail/iocp/win_signals.hpp>
43 #include <boost/corosio/native/detail/iocp/win_file_service.hpp>
44 #include <boost/corosio/native/detail/iocp/win_random_access_file_service.hpp>
45 #endif
46
47 namespace boost::corosio {
48
49 #if BOOST_COROSIO_HAS_EPOLL
50 detail::scheduler&
51 320x epoll_t::construct(capy::execution_context& ctx, unsigned concurrency_hint)
52 {
53 640x auto& sched = ctx.make_service<detail::epoll_scheduler>(
54 320x static_cast<int>(concurrency_hint));
55
56 320x ctx.make_service<detail::epoll_tcp_service>();
57 320x ctx.make_service<detail::epoll_tcp_acceptor_service>();
58 320x ctx.make_service<detail::epoll_udp_service>();
59
60 320x return sched;
61 }
62 #endif
63
64 #if BOOST_COROSIO_HAS_SELECT
65 detail::scheduler&
66 195x select_t::construct(capy::execution_context& ctx, unsigned concurrency_hint)
67 {
68 390x auto& sched = ctx.make_service<detail::select_scheduler>(
69 195x static_cast<int>(concurrency_hint));
70
71 195x ctx.make_service<detail::select_tcp_service>();
72 195x ctx.make_service<detail::select_tcp_acceptor_service>();
73 195x ctx.make_service<detail::select_udp_service>();
74
75 195x return sched;
76 }
77 #endif
78
79 #if BOOST_COROSIO_HAS_KQUEUE
80 detail::scheduler&
81 kqueue_t::construct(capy::execution_context& ctx, unsigned concurrency_hint)
82 {
83 auto& sched = ctx.make_service<detail::kqueue_scheduler>(
84 static_cast<int>(concurrency_hint));
85
86 ctx.make_service<detail::kqueue_tcp_service>();
87 ctx.make_service<detail::kqueue_tcp_acceptor_service>();
88 ctx.make_service<detail::kqueue_udp_service>();
89
90 return sched;
91 }
92 #endif
93
94 #if BOOST_COROSIO_HAS_IOCP
95 detail::scheduler&
96 iocp_t::construct(capy::execution_context& ctx, unsigned concurrency_hint)
97 {
98 auto& sched = ctx.make_service<detail::win_scheduler>(
99 static_cast<int>(concurrency_hint));
100
101 auto& sockets = ctx.make_service<detail::win_tcp_service>();
102 ctx.make_service<detail::win_tcp_acceptor_service>(sockets);
103 ctx.make_service<detail::win_udp_service>();
104 ctx.make_service<detail::win_signals>();
105 ctx.make_service<detail::win_file_service>();
106 ctx.make_service<detail::win_random_access_file_service>();
107
108 return sched;
109 }
110 #endif
111
112 namespace {
113
114 // Pre-create services that must exist before construct() runs.
115 void
116 pre_create_services(
117 capy::execution_context& ctx,
118 io_context_options const& opts)
119 {
120 #if BOOST_COROSIO_POSIX
121 // Pre-create the shared thread pool with the configured size.
122 // This must happen before construct() because the scheduler
123 // constructor creates file and resolver services that call
124 // get_or_create_pool(), which would create a 1-thread pool.
125 if (opts.thread_pool_size != 1)
126 ctx.make_service<detail::thread_pool>(opts.thread_pool_size);
127 #endif
128
129 (void)ctx;
130 (void)opts;
131 }
132
133 // Apply runtime tuning to the scheduler after construction.
134 void
135 apply_scheduler_options(
136 detail::scheduler& sched,
137 io_context_options const& opts)
138 {
139 #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_KQUEUE || BOOST_COROSIO_HAS_SELECT
140 auto& reactor =
141 static_cast<detail::reactor_scheduler_base&>(sched);
142 reactor.configure_reactor(
143 opts.max_events_per_poll,
144 opts.inline_budget_initial,
145 opts.inline_budget_max,
146 opts.unassisted_budget);
147 if (opts.single_threaded)
148 reactor.configure_single_threaded(true);
149 #endif
150
151 #if BOOST_COROSIO_HAS_IOCP
152 static_cast<detail::win_scheduler&>(sched).configure_iocp(
153 opts.gqcs_timeout_ms);
154 #endif
155
156 (void)sched;
157 (void)opts;
158 }
159
160 detail::scheduler&
161 125x construct_default(capy::execution_context& ctx, unsigned concurrency_hint)
162 {
163 #if BOOST_COROSIO_HAS_IOCP
164 return iocp_t::construct(ctx, concurrency_hint);
165 #elif BOOST_COROSIO_HAS_EPOLL
166 125x return epoll_t::construct(ctx, concurrency_hint);
167 #elif BOOST_COROSIO_HAS_KQUEUE
168 return kqueue_t::construct(ctx, concurrency_hint);
169 #elif BOOST_COROSIO_HAS_SELECT
170 return select_t::construct(ctx, concurrency_hint);
171 #endif
172 }
173
174 } // anonymous namespace
175
176 124x io_context::io_context() : io_context(std::thread::hardware_concurrency()) {}
177
178 125x io_context::io_context(unsigned concurrency_hint)
179 : capy::execution_context(this)
180 125x , sched_(&construct_default(*this, concurrency_hint))
181 {
182 125x }
183
184 io_context::io_context(
185 io_context_options const& opts,
186 unsigned concurrency_hint)
187 : capy::execution_context(this)
188 , sched_(nullptr)
189 {
190 pre_create_services(*this, opts);
191 sched_ = &construct_default(*this, concurrency_hint);
192 apply_scheduler_options(*sched_, opts);
193 }
194
195 void
196 io_context::apply_options_pre_(io_context_options const& opts)
197 {
198 pre_create_services(*this, opts);
199 }
200
201 void
202 io_context::apply_options_post_(io_context_options const& opts)
203 {
204 apply_scheduler_options(*sched_, opts);
205 }
206
207 515x io_context::~io_context()
208 {
209 515x shutdown();
210 515x destroy();
211 515x }
212
213 } // namespace boost::corosio
214