ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
callback_group.cpp
1 // Copyright 2015 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <algorithm>
16 #include <atomic>
17 #include <functional>
18 #include <memory>
19 #include <mutex>
20 #include <stdexcept>
21 
22 #include "rclcpp/callback_group.hpp"
23 #include "rclcpp/client.hpp"
24 #include "rclcpp/service.hpp"
25 #include "rclcpp/subscription_base.hpp"
26 #include "rclcpp/timer.hpp"
27 #include "rclcpp/waitable.hpp"
28 
30 using rclcpp::CallbackGroupType;
31 
32 CallbackGroup::CallbackGroup(
33  CallbackGroupType group_type,
34  const rclcpp::Context::WeakPtr & context,
35  bool automatically_add_to_executor_with_node)
36 : type_(group_type), associated_with_executor_(false),
37  can_be_taken_from_(true),
38  automatically_add_to_executor_with_node_(automatically_add_to_executor_with_node),
39  context_(context)
40 {}
41 
43 {
45 }
46 
47 std::atomic_bool &
49 {
50  return can_be_taken_from_;
51 }
52 
53 const CallbackGroupType &
55 {
56  return type_;
57 }
58 
59 size_t
61 {
62  std::lock_guard<std::mutex> lock(mutex_);
63  return
64  subscription_ptrs_.size() +
65  service_ptrs_.size() +
66  client_ptrs_.size() +
67  timer_ptrs_.size() +
68  waitable_ptrs_.size();
69 }
70 
72  const std::function<void(const rclcpp::SubscriptionBase::SharedPtr &)> & sub_func,
73  const std::function<void(const rclcpp::ServiceBase::SharedPtr &)> & service_func,
74  const std::function<void(const rclcpp::ClientBase::SharedPtr &)> & client_func,
75  const std::function<void(const rclcpp::TimerBase::SharedPtr &)> & timer_func,
76  const std::function<void(const rclcpp::Waitable::SharedPtr &)> & waitable_func) const
77 {
78  std::lock_guard<std::mutex> lock(mutex_);
79 
80  for (const rclcpp::SubscriptionBase::WeakPtr & weak_ptr : subscription_ptrs_) {
81  rclcpp::SubscriptionBase::SharedPtr ref_ptr = weak_ptr.lock();
82  if (ref_ptr) {
83  sub_func(ref_ptr);
84  }
85  }
86 
87  for (const rclcpp::ServiceBase::WeakPtr & weak_ptr : service_ptrs_) {
88  rclcpp::ServiceBase::SharedPtr ref_ptr = weak_ptr.lock();
89  if (ref_ptr) {
90  service_func(ref_ptr);
91  }
92  }
93 
94  for (const rclcpp::ClientBase::WeakPtr & weak_ptr : client_ptrs_) {
95  rclcpp::ClientBase::SharedPtr ref_ptr = weak_ptr.lock();
96  if (ref_ptr) {
97  client_func(ref_ptr);
98  }
99  }
100 
101  for (const rclcpp::TimerBase::WeakPtr & weak_ptr : timer_ptrs_) {
102  rclcpp::TimerBase::SharedPtr ref_ptr = weak_ptr.lock();
103  if (ref_ptr) {
104  timer_func(ref_ptr);
105  }
106  }
107 
108  for (const rclcpp::Waitable::WeakPtr & weak_ptr : waitable_ptrs_) {
109  rclcpp::Waitable::SharedPtr ref_ptr = weak_ptr.lock();
110  if (ref_ptr) {
111  waitable_func(ref_ptr);
112  }
113  }
114 }
115 
116 std::atomic_bool &
118 {
119  return associated_with_executor_;
120 }
121 
122 bool
124 {
125  return automatically_add_to_executor_with_node_;
126 }
127 
128 rclcpp::GuardCondition::SharedPtr
130 {
131  std::lock_guard<std::recursive_mutex> lock(notify_guard_condition_mutex_);
132  rclcpp::Context::SharedPtr context_ptr = context_.lock();
133  if (context_ptr && context_ptr->is_valid()) {
134  if (!notify_guard_condition_) {
135  notify_guard_condition_ = std::make_shared<rclcpp::GuardCondition>(context_ptr);
136  }
137  return notify_guard_condition_;
138  }
139  return nullptr;
140 }
141 
142 void
144 {
145  std::lock_guard<std::recursive_mutex> lock(notify_guard_condition_mutex_);
146  if (notify_guard_condition_) {
147  notify_guard_condition_->trigger();
148  }
149 }
150 
151 void
152 CallbackGroup::add_subscription(
153  const rclcpp::SubscriptionBase::SharedPtr & subscription_ptr)
154 {
155  std::lock_guard<std::mutex> lock(mutex_);
156  subscription_ptrs_.push_back(subscription_ptr);
157  subscription_ptrs_.erase(
158  std::remove_if(
159  subscription_ptrs_.begin(),
160  subscription_ptrs_.end(),
161  [](const rclcpp::SubscriptionBase::WeakPtr & x) {return x.expired();}),
162  subscription_ptrs_.end());
163 }
164 
165 void
166 CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr & timer_ptr)
167 {
168  std::lock_guard<std::mutex> lock(mutex_);
169  timer_ptrs_.push_back(timer_ptr);
170  timer_ptrs_.erase(
171  std::remove_if(
172  timer_ptrs_.begin(),
173  timer_ptrs_.end(),
174  [](const rclcpp::TimerBase::WeakPtr & x) {return x.expired();}),
175  timer_ptrs_.end());
176 }
177 
178 void
179 CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr & service_ptr)
180 {
181  std::lock_guard<std::mutex> lock(mutex_);
182  service_ptrs_.push_back(service_ptr);
183  service_ptrs_.erase(
184  std::remove_if(
185  service_ptrs_.begin(),
186  service_ptrs_.end(),
187  [](const rclcpp::ServiceBase::WeakPtr & x) {return x.expired();}),
188  service_ptrs_.end());
189 }
190 
191 void
192 CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr & client_ptr)
193 {
194  std::lock_guard<std::mutex> lock(mutex_);
195  client_ptrs_.push_back(client_ptr);
196  client_ptrs_.erase(
197  std::remove_if(
198  client_ptrs_.begin(),
199  client_ptrs_.end(),
200  [](const rclcpp::ClientBase::WeakPtr & x) {return x.expired();}),
201  client_ptrs_.end());
202 }
203 
204 void
205 CallbackGroup::add_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr)
206 {
207  std::lock_guard<std::mutex> lock(mutex_);
208  waitable_ptrs_.push_back(waitable_ptr);
209  waitable_ptrs_.erase(
210  std::remove_if(
211  waitable_ptrs_.begin(),
212  waitable_ptrs_.end(),
213  [](const rclcpp::Waitable::WeakPtr & x) {return x.expired();}),
214  waitable_ptrs_.end());
215 }
216 
217 void
218 CallbackGroup::remove_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr) noexcept
219 {
220  std::lock_guard<std::mutex> lock(mutex_);
221  for (auto iter = waitable_ptrs_.begin(); iter != waitable_ptrs_.end(); ++iter) {
222  const auto shared_ptr = iter->lock();
223  if (shared_ptr.get() == waitable_ptr.get()) {
224  waitable_ptrs_.erase(iter);
225  break;
226  }
227  }
228 }
RCLCPP_PUBLIC ~CallbackGroup()
Default destructor.
RCLCPP_PUBLIC rclcpp::GuardCondition::SharedPtr get_notify_guard_condition()
Retrieve the guard condition used to signal changes to this callback group.
RCLCPP_PUBLIC std::atomic_bool & get_associated_with_executor_atomic()
Return a reference to the 'associated with executor' atomic boolean.
RCLCPP_PUBLIC void trigger_notify_guard_condition()
Trigger the notify guard condition.
RCLCPP_PUBLIC bool automatically_add_to_executor_with_node() const
Return true if this callback group should be automatically added to an executor by the node.
RCLCPP_PUBLIC const CallbackGroupType & type() const
Get the group type.
RCLCPP_PUBLIC std::atomic_bool & can_be_taken_from()
Return a reference to the 'can be taken' atomic boolean.
RCLCPP_PUBLIC void collect_all_ptrs(const std::function< void(const rclcpp::SubscriptionBase::SharedPtr &)> &sub_func, const std::function< void(const rclcpp::ServiceBase::SharedPtr &)> &service_func, const std::function< void(const rclcpp::ClientBase::SharedPtr &)> &client_func, const std::function< void(const rclcpp::TimerBase::SharedPtr &)> &timer_func, const std::function< void(const rclcpp::Waitable::SharedPtr &)> &waitable_func) const
Collect all of the entity pointers contained in this callback group.
RCLCPP_PUBLIC size_t size() const
Get the total number of entities in this callback group.