-
Notifications
You must be signed in to change notification settings - Fork 10
Add multi-waiter support, cancel_one, and scheduler_impl intermediary #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughRefactors timer internals to use per-waiter state (waiter_node) enabling multiple concurrent waiters, introduces scheduler_impl as an intermediary caching timer_service pointers used by platform schedulers, and changes timer APIs to return std::size_t counts; several scheduler headers/source files and dispatch logic adjusted accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Coro1 as Coroutine 1
participant Coro2 as Coroutine 2
participant Timer as Timer
participant WN as Waiter Pool
participant TS as Timer Service
participant Sched as Scheduler
Coro1->>Timer: call wait()
Timer->>WN: allocate waiter_node for Coro1
WN-->>Timer: waiter_node created
Timer->>TS: register waiter_node (schedule/insert timer)
TS->>TS: insert/update timer heap/list
Coro2->>Timer: call wait() (same timer)
Timer->>WN: allocate waiter_node for Coro2
Timer->>TS: add waiter_node to timer's waiter list
rect rgba(100, 200, 100, 0.5)
Note over TS: timer expires
TS->>WN: process_expired -> collect waiter_nodes
TS->>Sched: post completions for waiter_nodes
end
Sched->>Coro1: resume (completion)
Sched->>Coro2: resume (completion)
Coro1->>WN: destroy/recycle waiter_node
Coro2->>WN: destroy/recycle waiter_node
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
An automated preview of the documentation is available at https://134.corosio.prtest3.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-02-12 04:35:58 UTC |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #134 +/- ##
===========================================
+ Coverage 81.03% 81.15% +0.11%
===========================================
Files 64 64
Lines 5557 5666 +109
===========================================
+ Hits 4503 4598 +95
- Misses 1054 1068 +14
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/corosio/src/detail/timer_service.cpp`:
- Around line 708-722: The insertion into the intrusive list in wait() (the
block calling waiters_.push_back(w)) races with cancel_waiter()'s
waiters_.remove(w); fix by serializing list mutations with the existing mutex_
(or by performing the push inside insert_timer so the insertion happens within
the same lock scope used for timer insertion). Concretely, either acquire mutex_
around the push_back in wait() and around any waiters_.empty() checks used in
update_timer/cancel_timer, or modify/extend insert_timer (e.g.,
insert_timer_and_waiter) to perform the first-waiter push inside its lock;
ensure cancel_waiter() continues to hold mutex_ while removing from
waiters_.remove.
- Around line 810-819: timer_service_create currently dereferences timer_svc_
from timer_service_access::get_scheduler(ioctx) without checking for nullptr;
add a null check after retrieving the pointer returned by
static_cast<timer_service_impl*>(...timer_svc_) and call
detail::throw_logic_error() (or equivalent) if svc is null before calling
svc->create_impl(), so the function safely handles an uninitialized timer_svc_.
🧹 Nitpick comments (2)
src/corosio/src/detail/timer_service.cpp (1)
331-356: Waiter node recycling doesn't resetstop_cb_or other optional state.
create_waiter()hands back a previously-used node without clearingstop_cb_,ec_value_, orimpl_. Whilewait()overwrites most fields andcompletion_op::operator()()resetsstop_cb_before recycling, it's worth verifying that every recycle path (especiallyshutdown(), where nodes are deleted rather than recycled) leaves no stalestop_cb_engaged. A defensivestop_cb_.reset()increate_waiter()(or a reinitialise helper) would make the contract self-documenting.include/boost/corosio/timer.hpp (1)
218-222:duration_casttruncation in templateexpires_afteris worth a@note.The
duration_castsilently truncates sub-nanosecond precision (e.g.,std::chrono::duration<double>→steady_clock::duration). Consider adding a brief@notethat the duration is truncated (not rounded) to the native resolution, mirroring Asio's documentation of the same overload.
Refactor timer internals to support multiple concurrent waiters on a single timer via per-waiter waiter_node linked with intrusive_list. Add constructors with initial expiry, cancel_one() for FIFO single cancellation, and return cancelled waiter counts from cancel(), expires_at(), and expires_after(). Add a waiter node cache for the wait-then-complete hot path. Introduce scheduler_impl as a private intermediary between the public scheduler interface and concrete backend schedulers (epoll, select, kqueue, iocp). Move timer_svc_ from each backend into scheduler_impl and remove the timer_svc() pure virtual from the public scheduler interface. Timer service lookup in timer_service_create now goes through timer_service_access to get the scheduler_impl and its cached timer_svc_ pointer. Update timer guide documentation with cancel_one, multi-waiter usage, and return values. Increase timer durations in cancel_one and stop-token-cancels-one tests from 50ms to 500ms to avoid CI flakiness on slow machines.
Refactor timer internals to support multiple concurrent waiters on a single timer via per-waiter waiter_node linked with intrusive_list. Add constructors with initial expiry, cancel_one() for FIFO single cancellation, and return cancelled waiter counts from cancel(), expires_at(), and expires_after(). Add a waiter node cache for the wait-then-complete hot path.
Introduce scheduler_impl as a private intermediary between the public scheduler interface and concrete backend schedulers (epoll, select, kqueue, iocp). Move timer_svc_ from each backend into scheduler_impl and remove the timer_svc() pure virtual from the public scheduler interface. Timer service lookup in timer_service_create now goes through timer_service_access to get the scheduler_impl and its cached timer_svc_ pointer. Update timer guide documentation with cancel_one, multi-waiter usage, and return values.
Resolves #126.
Resolves #97.
Summary by CodeRabbit
New Features
Improvements