Skip to content

feat: Added callback group events executor#3097

Open
jmachowinski wants to merge 10 commits intoros2:rollingfrom
cellumation:add_cbg_executor
Open

feat: Added callback group events executor#3097
jmachowinski wants to merge 10 commits intoros2:rollingfrom
cellumation:add_cbg_executor

Conversation

@jmachowinski
Copy link
Collaborator

This commit adds the callback group events executor. It features:

  • multithreading support
  • correct handling of sim time
  • usage of the events subsystem

Description

This moved the events cbg executor from cm_executors into rlcpp mainline.

Did you use Generative AI?

No

@alsora
Copy link
Collaborator

alsora commented Mar 15, 2026

@jmachowinski can you add this to the executor unit-tests?

@jmachowinski jmachowinski force-pushed the add_cbg_executor branch 3 times, most recently from f7b3021 to 7eb2fca Compare March 18, 2026 12:20
Janosch Machowinski and others added 5 commits March 20, 2026 13:30
This commit adds the callback group events executor.
It features:
 - multithreading support
 - correct handling of sim time
 - usage of the events subsystem

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>
Janosch Machowinski and others added 3 commits March 23, 2026 15:14
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
…ager

This code was copied straight from the executor and seems to be a
workaround for the multithreaded executor, that breaks in this use case.

The correct solution for us is to do the timer->call() from within the
worker thread. This fixes a deadlock due to double acquisition of an
internal lock within the timer manager.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
In case the next timer wakeup time is not changed by an insertion of a
timer, don't wake up the timer thread.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
@jmachowinski
Copy link
Collaborator Author

Pulls: #3097
Gist: https://gist.githubusercontent.com/jmachowinski/f9f71b19f46697be097713df6f9f6016/raw/f0f3fa2b988318178c70a0f1c9f90dbc50321ee8/ros2.repos
BUILD args:
TEST args:
ROS Distro: rolling
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/18616

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status
  • Windows Build Status

Janosch Machowinski added 2 commits March 23, 2026 15:39
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Copy link
Member

@skyegalaxy skyegalaxy left a comment

Choose a reason for hiding this comment

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

Aside from some spelling nits and a handful of small implementation questions, this is looking great! Very excited to get this over the finish line soon.

return FutureReturnCode::INTERRUPTED;
}

/// We need these fuction to be public, as we use them in the callback_group_scheduler
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// We need these fuction to be public, as we use them in the callback_group_scheduler
/// We need these functions to be public, as we use them in the callback_group_scheduler

added_nodes_cpy = added_nodes;
}

// *3 is a rough estimate of how many callback_group a node may have
Copy link
Member

Choose a reason for hiding this comment

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

What would happen in the case where a node might have more than 3 callback groups?

}
}

// FIXME inform scheduler about remove cbgs
Copy link
Member

Choose a reason for hiding this comment

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

what are the side-effects of leaving this as is and not informing the scheduler here?

// we need to shut down the timer manager first, as it might access the Schedulers
timer_manager->stop();

bool was_spining = spinning;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
bool was_spining = spinning;
bool was_spinning = spinning;

scheduler->unblock_one_worker_thread();
}

ready_entity.entitiy->execute_function();
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
ready_entity.entitiy->execute_function();
ready_entity.entity->execute_function();

}
}

template<class Executer>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
template<class Executer>
template<class Executor>

template<class Executer>
void benchmark_wait_for_work(benchmark::State & st)
{
class ExecuterDerived : public Executer
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
class ExecuterDerived : public Executer
class ExecutorDerived : public Executor

// start the cascasde
waitables[0]->trigger();

cascase_done.wait_for(lk, 500ms);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
cascase_done.wait_for(lk, 500ms);
cascade_done.wait_for(lk, 500ms);

* This is needed, as clocks may be deleted during normal operation,
* and be don't have a way to create a permanent ros time clock.
*/
class ClockConditionalVariable
Copy link
Member

Choose a reason for hiding this comment

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

I think it could be worth eventually merging the functionality of this ClockConditionalVariable variant with the existing one and cutting down on the duplicate code if it's not too complex to do.

public:
static rclcpp::Clock::SharedPtr get_clock(const rclcpp::TimerBase & timer)
{
// SUPER ugly hack, but we need the correct clock
Copy link
Member

Choose a reason for hiding this comment

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

is it worth expanding the timer API to provide access to its clock, or declaring the timer manager a friend class of TimerBase so the access is still limited?

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.

3 participants