Skip to content

Commit d2c0e86

Browse files
committed
Adapt executor interface to capy continuation API
Capy replaced coroutine_handle<> with continuation& in the executor post()/dispatch() signatures. continuation wraps a coroutine handle with an intrusive next pointer so executors can queue work without per-post heap allocation. Updated all post/dispatch call sites across every backend (epoll, kqueue, select, IOCP) and subsystem (timer, signal, resolver, tcp_server). Each call site stores a continuation with lifetime that outlives the executor queue residency.
1 parent 7d1ae92 commit d2c0e86

23 files changed

Lines changed: 146 additions & 84 deletions

include/boost/corosio/detail/dispatch_coro.hpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define BOOST_COROSIO_DETAIL_DISPATCH_CORO_HPP
1313

1414
#include <boost/corosio/io_context.hpp>
15+
#include <boost/capy/continuation.hpp>
1516
#include <boost/capy/ex/executor_ref.hpp>
1617
#include <boost/capy/detail/type_id.hpp>
1718
#include <coroutine>
@@ -20,25 +21,26 @@ namespace boost::corosio::detail {
2021

2122
/** Returns a handle for symmetric transfer on I/O completion.
2223
23-
If the executor is io_context::executor_type, returns `h`
24+
If the executor is io_context::executor_type, returns `c.h`
2425
directly (fast path). Otherwise dispatches through the
25-
executor, which returns `h` or `noop_coroutine()`.
26+
executor, which returns `c.h` or `noop_coroutine()`.
2627
2728
Callers in coroutine machinery should return the result
2829
for symmetric transfer. Callers at the scheduler pump
2930
level should call `.resume()` on the result.
3031
3132
@param ex The executor to dispatch through.
32-
@param h The coroutine handle to resume.
33+
@param c The continuation to dispatch. Must remain at a
34+
stable address until dequeued by the executor.
3335
3436
@return A handle for symmetric transfer or `std::noop_coroutine()`.
3537
*/
3638
inline std::coroutine_handle<>
37-
dispatch_coro(capy::executor_ref ex, std::coroutine_handle<> h)
39+
dispatch_coro(capy::executor_ref ex, capy::continuation& c)
3840
{
3941
if (ex.target<io_context::executor_type>() != nullptr)
40-
return h;
41-
return ex.dispatch(h);
42+
return c.h;
43+
return ex.dispatch(c);
4244
}
4345

4446
} // namespace boost::corosio::detail

include/boost/corosio/detail/timer_service.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ struct BOOST_COROSIO_SYMBOL_VISIBLE waiter_node
250250
timer_service::implementation* impl_ = nullptr;
251251
timer_service* svc_ = nullptr;
252252
std::coroutine_handle<> h_;
253+
capy::continuation* cont_ = nullptr;
253254
capy::executor_ref d_;
254255
std::error_code* ec_out_ = nullptr;
255256
std::stop_token token_;
@@ -282,7 +283,8 @@ struct timer_service::implementation final : timer::implementation
282283
std::coroutine_handle<>,
283284
capy::executor_ref,
284285
std::stop_token,
285-
std::error_code*) override;
286+
std::error_code*,
287+
capy::continuation*) override;
286288
};
287289

288290
// Thread-local caches avoid hot-path mutex acquisitions:
@@ -803,14 +805,14 @@ waiter_node::completion_op::operator()()
803805
if (w->ec_out_)
804806
*w->ec_out_ = w->ec_value_;
805807

806-
auto h = w->h_;
808+
auto* cont = w->cont_;
807809
auto d = w->d_;
808810
auto* svc = w->svc_;
809811
auto& sched = svc->get_scheduler();
810812

811813
svc->destroy_waiter(w);
812814

813-
d.post(h);
815+
d.post(*cont);
814816
sched.work_finished();
815817
}
816818

@@ -852,7 +854,8 @@ timer_service::implementation::wait(
852854
std::coroutine_handle<> h,
853855
capy::executor_ref d,
854856
std::stop_token token,
855-
std::error_code* ec)
857+
std::error_code* ec,
858+
capy::continuation* cont)
856859
{
857860
// Already-expired fast path — no waiter_node, no mutex.
858861
// Post instead of dispatch so the coroutine yields to the
@@ -863,7 +866,7 @@ timer_service::implementation::wait(
863866
{
864867
if (ec)
865868
*ec = {};
866-
d.post(h);
869+
d.post(*cont);
867870
return std::noop_coroutine();
868871
}
869872
}
@@ -872,6 +875,7 @@ timer_service::implementation::wait(
872875
w->impl_ = this;
873876
w->svc_ = svc_;
874877
w->h_ = h;
878+
w->cont_ = cont;
875879
w->d_ = d;
876880
w->token_ = std::move(token);
877881
w->ec_out_ = ec;

include/boost/corosio/io/io_timer.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <boost/corosio/detail/config.hpp>
1515
#include <boost/corosio/io/io_object.hpp>
16+
#include <boost/capy/continuation.hpp>
1617
#include <boost/capy/io_result.hpp>
1718
#include <boost/capy/error.hpp>
1819
#include <boost/capy/ex/executor_ref.hpp>
@@ -46,6 +47,7 @@ class BOOST_COROSIO_DECL io_timer : public io_object
4647
io_timer& t_;
4748
std::stop_token token_;
4849
mutable std::error_code ec_;
50+
capy::continuation cont_;
4951

5052
explicit wait_awaitable(io_timer& t) noexcept : t_(t) {}
5153

@@ -65,6 +67,7 @@ class BOOST_COROSIO_DECL io_timer : public io_object
6567
-> std::coroutine_handle<>
6668
{
6769
token_ = env->stop_token;
70+
cont_.h = h;
6871
auto& impl = t_.get();
6972
// Inline fast path: already expired and not in the heap
7073
if (impl.heap_index_ == implementation::npos &&
@@ -75,10 +78,10 @@ class BOOST_COROSIO_DECL io_timer : public io_object
7578
token_ = {}; // match normal path so await_resume
7679
// returns ec_, not a stale stop check
7780
auto d = env->executor;
78-
d.post(h);
81+
d.post(cont_);
7982
return std::noop_coroutine();
8083
}
81-
return impl.wait(h, env->executor, std::move(token_), &ec_);
84+
return impl.wait(h, env->executor, std::move(token_), &ec_, &cont_);
8285
}
8386
};
8487

@@ -109,7 +112,8 @@ class BOOST_COROSIO_DECL io_timer : public io_object
109112
std::coroutine_handle<>,
110113
capy::executor_ref,
111114
std::stop_token,
112-
std::error_code*) = 0;
115+
std::error_code*,
116+
capy::continuation*) = 0;
113117
};
114118

115119
/// The clock type used for time operations.

include/boost/corosio/io_context.hpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <boost/corosio/detail/config.hpp>
1616
#include <boost/corosio/detail/platform.hpp>
1717
#include <boost/corosio/detail/scheduler.hpp>
18+
#include <boost/capy/continuation.hpp>
1819
#include <boost/capy/ex/execution_context.hpp>
1920

2021
#include <chrono>
@@ -375,34 +376,34 @@ class io_context::executor_type
375376
ctx_->sched_->work_finished();
376377
}
377378

378-
/** Dispatch a coroutine handle.
379+
/** Dispatch a continuation.
379380
380381
Returns a handle for symmetric transfer. If called from
381-
within `run()`, returns `h`. Otherwise posts the coroutine
382+
within `run()`, returns `c.h`. Otherwise posts the coroutine
382383
for later execution and returns `std::noop_coroutine()`.
383384
384-
@param h The coroutine handle to dispatch.
385+
@param c The continuation to dispatch.
385386
386387
@return A handle for symmetric transfer or `std::noop_coroutine()`.
387388
*/
388-
std::coroutine_handle<> dispatch(std::coroutine_handle<> h) const
389+
std::coroutine_handle<> dispatch(capy::continuation& c) const
389390
{
390391
if (running_in_this_thread())
391-
return h;
392-
ctx_->sched_->post(h);
392+
return c.h;
393+
ctx_->sched_->post(c.h);
393394
return std::noop_coroutine();
394395
}
395396

396-
/** Post a coroutine for deferred execution.
397+
/** Post a continuation for deferred execution.
397398
398399
The coroutine will be resumed during a subsequent call to
399400
`run()`.
400401
401-
@param h The coroutine handle to post.
402+
@param c The continuation to post.
402403
*/
403-
void post(std::coroutine_handle<> h) const
404+
void post(capy::continuation& c) const
404405
{
405-
ctx_->sched_->post(h);
406+
ctx_->sched_->post(c.h);
406407
}
407408

408409
/** Compare two executors for equality.

include/boost/corosio/native/detail/epoll/epoll_tcp_acceptor_service.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ epoll_tcp_acceptor::accept(
177177
if (impl_out)
178178
*impl_out = nullptr;
179179
}
180-
return dispatch_coro(ex, h);
180+
op.cont.h = h;
181+
return dispatch_coro(ex, op.cont);
181182
}
182183

183184
op.accepted_fd = accepted;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct overlapped_op
6262

6363
long ready_ = 0;
6464
std::coroutine_handle<> h;
65+
capy::continuation cont;
6566
capy::executor_ref ex;
6667
std::error_code* ec_out = nullptr;
6768
std::size_t* bytes_out = nullptr;
@@ -144,7 +145,8 @@ struct overlapped_op
144145
if (bytes_out)
145146
*bytes_out = static_cast<std::size_t>(bytes_transferred);
146147

147-
dispatch_coro(ex, h).resume();
148+
cont.h = h;
149+
dispatch_coro(ex, cont).resume();
148150
}
149151

150152
/** Disarm cancellation and abandon the coroutine handle. */

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ resolve_op::do_complete(
270270

271271
op->cancel_handle = nullptr;
272272

273-
dispatch_coro(op->ex, op->h).resume();
273+
op->cont.h = op->h;
274+
dispatch_coro(op->ex, op->cont).resume();
274275
}
275276

276277
// reverse_resolve_op
@@ -314,7 +315,8 @@ reverse_resolve_op::do_complete(
314315
op->ep, std::move(op->stored_host), std::move(op->stored_service));
315316
}
316317

317-
dispatch_coro(op->ex, op->h).resume();
318+
op->cont.h = op->h;
319+
dispatch_coro(op->ex, op->cont).resume();
318320
}
319321

320322
// win_resolver

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <boost/corosio/signal_set.hpp>
2020
#include <boost/corosio/detail/intrusive.hpp>
2121
#include <boost/corosio/detail/scheduler_op.hpp>
22+
#include <boost/capy/continuation.hpp>
2223
#include <boost/capy/ex/executor_ref.hpp>
2324

2425
#include <coroutine>
@@ -43,6 +44,7 @@ enum
4344
struct signal_op : scheduler_op
4445
{
4546
std::coroutine_handle<> h;
47+
capy::continuation cont;
4648
capy::executor_ref d;
4749
std::error_code* ec_out = nullptr;
4850
int* signal_out = nullptr;

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ signal_op::do_complete(
304304
auto* service = op->svc;
305305
op->svc = nullptr;
306306

307-
dispatch_coro(op->d, op->h).resume();
307+
op->cont.h = op->h;
308+
dispatch_coro(op->d, op->cont).resume();
308309

309310
if (service)
310311
service->work_finished();
@@ -337,7 +338,8 @@ win_signal::wait(
337338
*ec = make_error_code(capy::error::canceled);
338339
if (signal_out)
339340
*signal_out = 0;
340-
dispatch_coro(d, h).resume();
341+
pending_op_.cont.h = h;
342+
dispatch_coro(d, pending_op_.cont).resume();
341343
// completion is always posted to scheduler queue, never inline.
342344
return std::noop_coroutine();
343345
}
@@ -610,7 +612,8 @@ win_signals::cancel_wait(win_signal& impl)
610612
*op->ec_out = make_error_code(capy::error::canceled);
611613
if (op->signal_out)
612614
*op->signal_out = 0;
613-
dispatch_coro(op->d, op->h).resume();
615+
op->cont.h = op->h;
616+
dispatch_coro(op->d, op->cont).resume();
614617
sched_.work_finished();
615618
}
616619
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,11 @@ accept_op::do_complete(
238238
*op->impl_out = nullptr;
239239
}
240240

241-
auto saved_h = op->h;
241+
op->cont.h = op->h;
242242
auto saved_ex = op->ex;
243243
auto prevent_premature_destruction = std::move(op->acceptor_ptr);
244244

245-
dispatch_coro(saved_ex, saved_h).resume();
245+
dispatch_coro(saved_ex, op->cont).resume();
246246
}
247247

248248
// connect_op completion handler

0 commit comments

Comments
 (0)