-
Notifications
You must be signed in to change notification settings - Fork 418
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
Add in callback_groups_for_each. #1723
Conversation
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.
LGTM with green CI.
I have only left some minor comments
@@ -2733,13 +2733,33 @@ TEST_F(TestNode, get_publishers_subscriptions_info_by_topic) { | |||
|
|||
TEST_F(TestNode, callback_groups) { | |||
auto node = std::make_shared<rclcpp::Node>("node", "ns"); | |||
size_t num_callback_groups_in_basic_node = node->get_callback_groups().size(); |
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.
we could still use get_callback_groups().size()
here.
If we want to delete get_callback_groups()
, which is a good idea IMO, we could add a callback_groups_size()
method.
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.
Yeah, we could. Right now we only seem to get the size
of the callback group in tests, so I'm OK with the more verbose way of doing it. In the future if we decide we need it in more places, we can add it in.
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.
I also think it would be a good idea to get rid of get_callback_groups()
in its current form, because a) it would force users of it that are outside of our code base to consider if they're using it in a thread-unsafe way and b) because we could provide a const method that returns a copy of the callback groups vector instead, which could be used for size()
and other things, which I would prefer over a dedicated get_callback_groups_size()
.
(a bit unrelated) Why are we storing the "callback groups" that we don't need to automatically add to the executor in the node? It seems to be unnecessary. |
1e6770f
to
551dbcf
Compare
I'm not sure I totally understand the question. As far as I can tell, we need to store each callback group we create so that we can later iterate over them, either via Or did you have a different way in mind to find and iterate over the callback groups? |
AFAIS, in all places where we iterate over callback groups we're skipping the ones that should not be automatically added to the executor, e.g. rclcpp/rclcpp/src/rclcpp/executor.cpp Line 196 in 551dbcf
It seems that the only reason that we had for storing a callback groups in Node was for adding callback groups to the executor, so I don't see why we also need to store the ones we want to handle separately.
edit: The |
Ah, I see what you mean. I agree that we should maybe re-examine how this is done. That said, I don't necessarily want to do it in here; this PR is already large, and if we decide to go ahead and remove What I'll do is to open a separate issue to address that, and we can talk about it there. |
rclcpp/src/rclcpp/executors/static_executor_entities_collector.cpp
Outdated
Show resolved
Hide resolved
@@ -2733,13 +2733,33 @@ TEST_F(TestNode, get_publishers_subscriptions_info_by_topic) { | |||
|
|||
TEST_F(TestNode, callback_groups) { | |||
auto node = std::make_shared<rclcpp::Node>("node", "ns"); | |||
size_t num_callback_groups_in_basic_node = node->get_callback_groups().size(); |
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.
I also think it would be a good idea to get rid of get_callback_groups()
in its current form, because a) it would force users of it that are outside of our code base to consider if they're using it in a thread-unsafe way and b) because we could provide a const method that returns a copy of the callback groups vector instead, which could be used for size()
and other things, which I would prefer over a dedicated get_callback_groups_size()
.
I also think we might not need to store the callback groups that aren't automatically added to an executor, and that they could even be constructed directly. |
The only thing that might be affected is that notifying any executor that the callback group is associated with that something has been added/removed (the executor needs to interrupt itself in this case to rebuild the wait set), sometimes goes through the node, but again that might be only if the |
The main reason to add this method in is to make accesses to the callback_groups_ vector thread-safe. By having a callback_groups_for_each that accepts a std::function, we can just have the callers give us the callback they are interested in, and we can take care of the locking. The rest of this fairly large PR is cleaning up all of the places that use get_callback_groups() to instead use callback_groups_for_each(). Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
Callers should change to using for_each_callback_group(), or store the callback groups they need internally. Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
551dbcf
to
9ff1acf
Compare
All right. I've responded to all of the inline comments, I believe. I also rebased this onto the latest to get #1726 so windows CI will pass. Finally, I've removed |
Full CI (including ros2/examples#320): |
The failing test on Windows is flakey; it also failed on Windows in https://ci.ros2.org/view/nightly/job/nightly_win_rep/2312. So this is otherwise green. Since I also have approvals, I'm going to go ahead and merge this one along with ros2/examples#320 . |
👍 |
The main reason to add this method in is to make accesses to the
callback_groups_ vector thread-safe. By having a
callback_groups_for_each that accepts a std::function, we can
just have the callers give us the callback they are interested
in, and we can take care of the locking.
The rest of this fairly large PR is cleaning up all of the places
that use get_callback_groups() to instead use
callback_groups_for_each().
Signed-off-by: Chris Lalancette clalancette@openrobotics.org
This is the solution to the problem identified in ros-simulation/gazebo_ros_pkgs#1296 . In short, when using a thread to deal with
use_sim_time
, it is the case that the callbacks_group_ vector can be accessed by two threads simultaneously. In certain circumstances (particularly startup time), this can lead to a crash. By doing proper locking, we avoid the crash.There are two other things that I'd like to discuss in relation to this:
get_callback_groups()
method? I have not done that here, but I really think we should. It is not currently possible to access thecallback_groups_
vector in a thread-safe way. Alternatively we could deprecate it, but given that there is really no safe way to use it I'd rather just remove it.callback_groups_for_each()
method, I replicated the previous structure where there is a method on both theNodeBase
andNode
objects. The latter is a thin wrapper around the former. But it seems redundant;Node
has a public method to get theNodeBase
, andNodeBase
has the public methodcallback_groups_for_each()
. So anyplace that currently doesnode->callback_groups_for_each()
could be trivially changed tonode->node_base()->callback_groups_for_each()
. I'd opt for removing the method from theNode
class, but I'm interested in what others thinkQuestions, comments, and reviews are all very welcome.