17 #include "rclcpp/executors/executor_entities_collector.hpp"
18 #include "rclcpp/executors/executor_notify_waitable.hpp"
19 #include "rclcpp/node_interfaces/node_base_interface.hpp"
27 const std::shared_ptr<ExecutorNotifyWaitable> & notify_waitable)
28 : notify_waitable_(notify_waitable)
34 for (
auto weak_node_it = weak_nodes_.begin(); weak_node_it != weak_nodes_.end(); ) {
38 for (
auto weak_group_it = automatically_added_groups_.begin();
39 weak_group_it != automatically_added_groups_.end(); )
44 for (
auto weak_group_it = manually_added_groups_.begin();
45 weak_group_it != manually_added_groups_.end(); )
50 for (
const auto & weak_node_ptr : pending_added_nodes_) {
51 auto node_ptr = weak_node_ptr.lock();
53 node_ptr->get_associated_with_executor_atomic().store(
false);
56 pending_added_nodes_.clear();
57 pending_removed_nodes_.clear();
59 for (
const auto & weak_group_ptr : pending_manually_added_groups_) {
60 auto group_ptr = weak_group_ptr.lock();
62 group_ptr->get_associated_with_executor_atomic().store(
false);
65 auto guard_condition_it = weak_groups_to_guard_conditions_.find(weak_group_ptr);
66 if (guard_condition_it != weak_groups_to_guard_conditions_.end()) {
68 weak_groups_to_guard_conditions_.erase(guard_condition_it);
71 pending_manually_added_groups_.clear();
72 pending_manually_removed_groups_.clear();
78 std::lock_guard<std::mutex> lock(
mutex_);
79 return pending_manually_added_groups_.size() != 0 ||
80 pending_manually_removed_groups_.size() != 0 ||
81 pending_added_nodes_.size() != 0 ||
82 pending_removed_nodes_.size() != 0;
87 const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr)
90 std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
91 if (has_executor.exchange(
true)) {
92 throw std::runtime_error(
93 std::string(
"Node '") + node_ptr->get_fully_qualified_name() +
94 "' has already been added to an executor.");
97 std::lock_guard<std::mutex> lock(
mutex_);
98 bool associated = weak_nodes_.count(node_ptr) != 0;
99 bool add_queued = pending_added_nodes_.count(node_ptr) != 0;
100 bool remove_queued = pending_removed_nodes_.count(node_ptr) != 0;
102 if ((associated || add_queued) && !remove_queued) {
103 throw std::runtime_error(
104 std::string(
"Node '") + node_ptr->get_fully_qualified_name() +
105 "' has already been added to this executor.");
108 this->pending_added_nodes_.insert(node_ptr);
113 const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr)
115 std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
116 if (!has_executor.exchange(
false)) {
117 throw std::runtime_error(
118 std::string(
"Node '") + node_ptr->get_fully_qualified_name() +
119 "' needs to be associated with an executor.");
122 std::lock_guard<std::mutex> lock(
mutex_);
123 bool associated = weak_nodes_.count(node_ptr) != 0;
124 bool add_queued = pending_added_nodes_.count(node_ptr) != 0;
125 bool remove_queued = pending_removed_nodes_.count(node_ptr) != 0;
127 if (!(associated || add_queued) || remove_queued) {
128 throw std::runtime_error(
129 std::string(
"Node '") + node_ptr->get_fully_qualified_name() +
130 "' needs to be associated with this executor.");
133 this->pending_removed_nodes_.insert(node_ptr);
139 std::atomic_bool & has_executor = group_ptr->get_associated_with_executor_atomic();
140 if (has_executor.exchange(
true)) {
141 throw std::runtime_error(
"Callback group has already been added to an executor.");
144 std::lock_guard<std::mutex> lock(
mutex_);
145 bool associated = manually_added_groups_.count(group_ptr) != 0;
146 bool add_queued = pending_manually_added_groups_.count(group_ptr) != 0;
147 bool remove_queued = pending_manually_removed_groups_.count(group_ptr) != 0;
149 if ((associated || add_queued) && !remove_queued) {
150 throw std::runtime_error(
"Callback group has already been added to this executor.");
153 this->pending_manually_added_groups_.insert(group_ptr);
156 auto group_guard_condition = group_ptr->get_notify_guard_condition();
157 weak_groups_to_guard_conditions_.insert({group_ptr, group_guard_condition});
164 if (!group_ptr->get_associated_with_executor_atomic().load()) {
165 throw std::runtime_error(
"Callback group needs to be associated with an executor.");
177 auto weak_group_ptr = rclcpp::CallbackGroup::WeakPtr(group_ptr);
178 std::lock_guard<std::mutex> lock(
mutex_);
179 bool associated = manually_added_groups_.count(group_ptr) != 0;
180 bool add_queued = pending_manually_added_groups_.count(group_ptr) != 0;
181 bool remove_queued = pending_manually_removed_groups_.count(group_ptr) != 0;
183 if (!(associated || add_queued) || remove_queued) {
184 throw std::runtime_error(
"Callback group needs to be associated with this executor.");
187 this->pending_manually_removed_groups_.insert(group_ptr);
190 std::vector<rclcpp::CallbackGroup::WeakPtr>
193 std::vector<rclcpp::CallbackGroup::WeakPtr> groups;
194 std::lock_guard<std::mutex> lock(
mutex_);
195 for (
const auto & group_ptr : manually_added_groups_) {
196 groups.push_back(group_ptr);
198 for (
auto const & group_ptr : automatically_added_groups_) {
199 groups.push_back(group_ptr);
204 std::vector<rclcpp::CallbackGroup::WeakPtr>
207 std::vector<rclcpp::CallbackGroup::WeakPtr> groups;
208 std::lock_guard<std::mutex> lock(
mutex_);
209 for (
const auto & group_ptr : manually_added_groups_) {
210 groups.push_back(group_ptr);
215 std::vector<rclcpp::CallbackGroup::WeakPtr>
218 std::vector<rclcpp::CallbackGroup::WeakPtr> groups;
219 std::lock_guard<std::mutex> lock(
mutex_);
220 for (
auto const & group_ptr : automatically_added_groups_) {
221 groups.push_back(group_ptr);
229 std::lock_guard<std::mutex> lock(
mutex_);
235 ExecutorEntitiesCollector::NodeCollection::iterator
239 auto guard_condition_it = weak_nodes_to_guard_conditions_.find(*weak_node);
240 if (guard_condition_it != weak_nodes_to_guard_conditions_.end()) {
242 weak_nodes_to_guard_conditions_.erase(guard_condition_it);
246 auto node_ptr = weak_node->lock();
248 std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
249 has_executor.store(
false);
253 return weak_nodes_.erase(weak_node);
256 ExecutorEntitiesCollector::CallbackGroupCollection::iterator
258 CallbackGroupCollection::iterator weak_group_it,
259 CallbackGroupCollection & collection
263 auto guard_condition_it = weak_groups_to_guard_conditions_.find(*weak_group_it);
264 if (guard_condition_it != weak_groups_to_guard_conditions_.end()) {
266 weak_groups_to_guard_conditions_.erase(guard_condition_it);
270 auto group_ptr = weak_group_it->lock();
282 std::atomic_bool & has_executor = group_ptr->get_associated_with_executor_atomic();
283 has_executor.store(
false);
287 return collection.erase(weak_group_it);
292 const rclcpp::CallbackGroup::SharedPtr & group_ptr,
293 CallbackGroupCollection & collection)
295 auto iter = collection.insert(group_ptr);
296 if (iter.second ==
false) {
297 throw std::runtime_error(
"Callback group has already been added to this executor.");
301 auto group_guard_condition = group_ptr->get_notify_guard_condition();
302 weak_groups_to_guard_conditions_.insert({group_ptr, group_guard_condition});
309 for (
const auto & weak_node_ptr : pending_added_nodes_) {
310 auto node_ptr = weak_node_ptr.lock();
314 weak_nodes_.insert(weak_node_ptr);
318 auto node_guard_condition = node_ptr->get_shared_notify_guard_condition();
319 weak_nodes_to_guard_conditions_.insert({weak_node_ptr, node_guard_condition});
322 pending_added_nodes_.clear();
324 for (
const auto & weak_node_ptr : pending_removed_nodes_) {
325 auto node_it = weak_nodes_.find(weak_node_ptr);
326 if (node_it != weak_nodes_.end()) {
331 if (!weak_node_ptr.expired()) {
332 throw std::runtime_error(
"Node needs to be associated with this executor.");
336 auto node_ptr = weak_node_ptr.lock();
338 for (
auto group_it = automatically_added_groups_.begin();
339 group_it != automatically_added_groups_.end(); )
341 auto group_ptr = group_it->lock();
342 if (node_ptr->callback_group_in_node(group_ptr)) {
350 pending_removed_nodes_.clear();
352 for (
const auto & weak_group_ptr : pending_manually_added_groups_) {
353 auto group_ptr = weak_group_ptr.lock();
358 auto guard_condition_it = weak_groups_to_guard_conditions_.find(weak_group_ptr);
359 if (guard_condition_it != weak_groups_to_guard_conditions_.end()) {
361 weak_groups_to_guard_conditions_.erase(guard_condition_it);
365 pending_manually_added_groups_.clear();
367 for (
const auto & weak_group_ptr : pending_manually_removed_groups_) {
368 auto group_ptr = weak_group_ptr.lock();
370 auto group_it = manually_added_groups_.find(group_ptr);
371 if (group_it != manually_added_groups_.end()) {
374 throw std::runtime_error(
375 "Attempting to remove a callback group not added to this executor.");
379 pending_manually_removed_groups_.clear();
384 const NodeCollection & nodes_to_check)
386 for (
auto & weak_node : nodes_to_check) {
387 auto node = weak_node.lock();
389 node->for_each_callback_group(
390 [
this, node](
const rclcpp::CallbackGroup::SharedPtr & group_ptr)
392 if (!group_ptr->get_associated_with_executor_atomic().load() &&
393 group_ptr->automatically_add_to_executor_with_node())
395 std::atomic_bool & has_executor = group_ptr->get_associated_with_executor_atomic();
396 if (has_executor.exchange(true)) {
397 throw std::runtime_error(
"Callback group has already been added to an executor.");
399 this->add_callback_group_to_collection(group_ptr, this->automatically_added_groups_);
407 ExecutorEntitiesCollector::prune_invalid_nodes_and_groups()
409 for (
auto node_it = weak_nodes_.begin();
410 node_it != weak_nodes_.end(); )
412 if (node_it->expired()) {
413 node_it = remove_weak_node(node_it);
418 for (
auto group_it = automatically_added_groups_.begin();
419 group_it != automatically_added_groups_.end(); )
421 if (group_it->expired()) {
422 group_it = remove_weak_callback_group(group_it, automatically_added_groups_);
427 for (
auto group_it = manually_added_groups_.begin();
428 group_it != manually_added_groups_.end(); )
430 if (group_it->expired()) {
431 group_it = remove_weak_callback_group(group_it, manually_added_groups_);
RCLCPP_PUBLIC NodeCollection::iterator remove_weak_node(NodeCollection::iterator weak_node) RCPPUTILS_TSA_REQUIRES(mutex_)
Implementation of removing a node from the collector.
RCLCPP_PUBLIC void add_node(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr &node_ptr)
Add a node to the entity collector.
RCLCPP_PUBLIC void add_callback_group_to_collection(const rclcpp::CallbackGroup::SharedPtr &group_ptr, CallbackGroupCollection &collection) RCPPUTILS_TSA_REQUIRES(mutex_)
Implementation of adding a callback group.
RCLCPP_PUBLIC void prune_invalid_nodes_and_groups() RCPPUTILS_TSA_REQUIRES(mutex_)
Check all nodes and group for expired weak pointers and remove them.
std::shared_ptr< ExecutorNotifyWaitable > notify_waitable_
Waitable to add guard conditions to.
RCLCPP_PUBLIC void update_collections()
Update the underlying collections.
RCLCPP_PUBLIC std::vector< rclcpp::CallbackGroup::WeakPtr > get_all_callback_groups() const
Get all callback groups known to this entity collector.
bool has_pending() const
Indicate if the entities collector has pending additions or removals.
RCLCPP_PUBLIC void process_queues() RCPPUTILS_TSA_REQUIRES(mutex_)
Iterate over queued added/remove nodes and callback_groups.
RCLCPP_PUBLIC void add_callback_group(const rclcpp::CallbackGroup::SharedPtr &group_ptr)
Add a callback group to the entity collector.
RCLCPP_PUBLIC ExecutorEntitiesCollector(const std::shared_ptr< ExecutorNotifyWaitable > ¬ify_waitable)
Constructor.
RCLCPP_PUBLIC void remove_callback_group(const rclcpp::CallbackGroup::SharedPtr &group_ptr)
Remove a callback group from the entity collector.
RCLCPP_PUBLIC ~ExecutorEntitiesCollector()
Destructor.
std::mutex mutex_
mutex to protect collections and pending queues
RCLCPP_PUBLIC void add_automatically_associated_callback_groups(const NodeCollection &nodes_to_check) RCPPUTILS_TSA_REQUIRES(mutex_)
RCLCPP_PUBLIC std::vector< rclcpp::CallbackGroup::WeakPtr > get_automatically_added_callback_groups() const
Get automatically-added callback groups known to this entity collector.
RCLCPP_PUBLIC void remove_node(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr &node_ptr)
Remove a node from the entity collector.
RCLCPP_PUBLIC CallbackGroupCollection::iterator remove_weak_callback_group(CallbackGroupCollection::iterator weak_group_it, CallbackGroupCollection &collection) RCPPUTILS_TSA_REQUIRES(mutex_)
Implementation of removing a callback group from the collector.
RCLCPP_PUBLIC std::vector< rclcpp::CallbackGroup::WeakPtr > get_manually_added_callback_groups() const
Get manually-added callback groups known to this entity collector.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.