Skip to content

Track every waiting coroutine with Waiting - #65

Merged
otamachan merged 2 commits into
mainfrom
unify-waiting
Oct 18, 2026
Merged

otamachan merged 2 commits into
mainfrom
unify-waiting

Conversation

@otamachan

@otamachan otamachan commented Oct 18, 2026 •

Copy link
Copy Markdown
Owner

Follows #63 and #64. Refactor only; no behavior change intended.

Each awaiter guarded the handle it hands out in its own way: Event and Mutex an active flag, send_request / send_goal a shared State with a done flag plus a destructor, TopicStream / GoalStream a destructor clearing waiter_, Sleep a done flag, and register_cancel an is_done predicate plus a weak_ptr to the stop callback. #63 and #64 added Waiting for the cases that had no guard.

Now every awaiter owns a Waiting, and whoever resumes it holds a weak_ptr to it:

  • Waiting::take() hands the handle out once (atomic exchange). Whichever of completion and cancellation takes it first resumes the coroutine; this replaces the active / done flags and the is_done predicates.
  • The weak_ptr expires with the awaiter, so a destroyed awaiter is never resumed; this replaces the destructors.
  • Three helpers in executor.hpp:
    • resume_now(ctx, w): take and resume on the spot (Event::set, Mutex::unlock, stream messages, timer ticks, service responses).
    • post_resume(ctx, w[, claimed]): take now, resume on the executor if the awaiter is still alive (TF, goal response, Channel::send / close, and the synchronous stop callbacks of Sleep, TimerStream and Channel, which withdraw the waiter on the spot as before). Unlike Resume a posted waiter only while its awaiter is alive #63's version it takes at call time, as the replaced done flags were set at call time.
    • register_cancel(out, token, ctx, waiting, action): on a stop request, post; if the handle is still there, run action and resume.

Removed: the active flags and Waiter structs in Event / Mutex, the State structs of SendRequestAwaiter / SendGoalAwaiter (callbacks write into the awaiter only while its Waiting is alive), PendingRequest::active and ~LookupTransformAwaiter (a destroyed awaiter's request is dropped on the next check_pending), SleepAwaiter::done, and the destructors of Event, Mutex, SendRequest, SendGoal, TopicStream and TfBuffer awaiters. GoalStream::NextAwaiter keeps its destructor, which still cancels the goal.

Mutex::LockAwaiter::await_resume checked token.stop_requested() && !(active && *active). *active was always false by the time the awaiter resumed (both unlock and the cancellation cleared it), so this is token.stop_requested(), which is what it checks now.

colcon test passes (354 tests, ASan build, LeakSanitizer off), including the tests added in #63 and #64.

Base automatically changed from guard-held-handles to main October 18, 2026 06:15
Each awaiter guarded its handed-out handle in its own way: Event and
Mutex an active flag, send_request and send_goal a shared State with a
done flag and a destructor, the streams a destructor clearing waiter_,
Sleep a done flag, and register_cancel an is_done predicate plus a
weak_ptr to the stop callback.

All of them now hold a Waiting, and whoever resumes them a weak_ptr to
it. Waiting's handle is taken once, which decides between completion and
cancellation, and the weak_ptr expiring with the awaiter keeps a
destroyed one from being resumed. resume_now, post_resume and
register_cancel(waiting, action) are the three ways to resume it.

The per-awaiter flags, State structs, is_done predicates and destructors
go away, except GoalStream::NextAwaiter's, which still cancels the goal.
TfBuffer drops a destroyed awaiter's request on the next check instead of
in the destructor. No behavior change otherwise.
register_cancel deferred withdrawing it to the executor, so a send that
arrived in between won and returned a value despite the stop request.
@otamachan
otamachan merged commit 7a54000 into main Oct 18, 2026
6 checks passed
@otamachan
otamachan deleted the unify-waiting branch October 18, 2026 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant