Skip to content

add support for reentrant callback group to EventsCBGExecutor#3178

Open
armaho wants to merge 2 commits into
ros2:rollingfrom
armaho:events_cbg_executor_reentrant
Open

add support for reentrant callback group to EventsCBGExecutor#3178
armaho wants to merge 2 commits into
ros2:rollingfrom
armaho:events_cbg_executor_reentrant

Conversation

@armaho

@armaho armaho commented Jun 18, 2026

Copy link
Copy Markdown

Description

Fixes #3175

Is this user-facing behavior change?

Did you use Generative AI?

No

Additional Information

Signed-off-by: Arman Hosseini <armahosseini878787@gmail.com>
@skyegalaxy skyegalaxy requested review from jmachowinski and skyegalaxy and removed request for jmachowinski June 18, 2026 16:00

@skyegalaxy skyegalaxy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with green CI. will let @jmachowinski take a pass as well

{
ready_callback_groups.erase(it);
}
return CBGScheduler::ExecutableEntityWithInfo{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self to remove C++20 initialization when backporting this to Jazzy and Kilted specifically

@skyegalaxy

Copy link
Copy Markdown
Member

actually @armaho can you add a test which exercises the reentrant path like we discussed at the client library WG meeting?

@armaho

armaho commented Jun 19, 2026

Copy link
Copy Markdown
Author

@skyegalaxy

Sure let me see how to test it.

@mergify

mergify Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

…er EventCBGExecutor

Signed-off-by: Arman Hosseini <armahosseini878787@gmail.com>
@armaho armaho force-pushed the events_cbg_executor_reentrant branch from 554512d to 855d1b2 Compare June 19, 2026 13:29
@armaho

armaho commented Jun 19, 2026

Copy link
Copy Markdown
Author

@skyegalaxy

I just added a test covering the reentrant callback group behavior. Could you take another look when you have time?

@jmachowinski jmachowinski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reply.
I wonder if it makes sense to introduce a second class of callback handle, providing a seperate logic.
In this case the ready queue would be something like
std::deque<std::variant<ReentrantCallbackGroupHandle *, MutalExclusiveCallbackGroupHandle *>

Even though this would lead to some code duplication, I think it would make the code easier and better understandable in the end. The current approach of selectively doing things made it hard to understand what is going on.

I also think the compiler might optimize the variant better.

ready_cbg->get_type() == CallbackGroupType::MutuallyExclusive ||
!ready_cbg->has_ready_entities())
{
ready_callback_groups.erase(it);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a bad idea, I would rather delete it always and push it back later.
Otherwise we might get starvation on one callback group.

Comment on lines +95 to +97
if (type != CallbackGroupType::Reentrant) {
not_ready = false;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is odd, this function is called after execution.
So you are basically blocking the callback group with this.
Note the inverted naming, not_ready = false actually means it is ready.

Comment on lines +234 to +252

// Reentrant callback groups might not be removed from the queue when one of
// their entities starts executing.
if (handle->get_type() == CallbackGroupType::Reentrant) {
bool already_in_queue = false;

for (auto it = ready_callback_groups.begin(); it != ready_callback_groups.end(); it++) {
if (*it == handle) {
already_in_queue = true;
break;
}
}

if (!already_in_queue) {
ready_callback_groups.push_back(handle);
}
} else {
ready_callback_groups.push_back(handle);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big no go, you introduce O(n) characteristics by searching the ready list.
This code should actually not be needed as the callback group handle should hold the information
if it is in the queue or not.

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.

EventsCBGExecutor treats reentrant callback groups like they're mutually exclusive

3 participants