ROS 2 rclcpp + rcl - kilted  kilted
ROS 2 C++ Client Library with ROS Client Library
any_subscription_callback.hpp
1 // Copyright 2014 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 #ifndef RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
16 #define RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
17 
18 #include <functional>
19 #include <memory>
20 #include <stdexcept>
21 #include <type_traits>
22 #include <utility>
23 #include <variant>
24 
25 #include "rosidl_runtime_cpp/traits.hpp"
26 #include "tracetools/tracetools.h"
27 #include "tracetools/utils.hpp"
28 
29 #include "rclcpp/allocator/allocator_common.hpp"
30 #include "rclcpp/detail/subscription_callback_type_helper.hpp"
31 #include "rclcpp/function_traits.hpp"
32 #include "rclcpp/message_info.hpp"
33 #include "rclcpp/serialization.hpp"
34 #include "rclcpp/serialized_message.hpp"
35 #include "rclcpp/type_adapter.hpp"
36 
37 namespace rclcpp
38 {
39 
40 namespace detail
41 {
42 
43 template<class>
44 inline constexpr bool always_false_v = false;
45 
46 template<typename MessageT, typename AllocatorT>
48 {
49  using AllocTraits = allocator::AllocRebind<MessageT, AllocatorT>;
50  using Alloc = typename AllocTraits::allocator_type;
51  using Deleter = allocator::Deleter<Alloc, MessageT>;
52 };
53 
55 template<typename MessageT, typename AllocatorT>
57 {
59  using SubscribedType = typename rclcpp::TypeAdapter<MessageT>::custom_type;
61  using ROSMessageType = typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
62 
63  using SubscribedMessageDeleter =
64  typename MessageDeleterHelper<SubscribedType, AllocatorT>::Deleter;
65  using ROSMessageDeleter =
66  typename MessageDeleterHelper<ROSMessageType, AllocatorT>::Deleter;
67  using SerializedMessageDeleter =
68  typename MessageDeleterHelper<rclcpp::SerializedMessage, AllocatorT>::Deleter;
69 
70  using ConstRefCallback =
71  std::function<void (const SubscribedType &)>;
72  using ConstRefROSMessageCallback =
73  std::function<void (const ROSMessageType &)>;
74  using ConstRefWithInfoCallback =
75  std::function<void (const SubscribedType &, const rclcpp::MessageInfo &)>;
76  using ConstRefWithInfoROSMessageCallback =
77  std::function<void (const ROSMessageType &, const rclcpp::MessageInfo &)>;
78  using ConstRefSerializedMessageCallback =
79  std::function<void (const rclcpp::SerializedMessage &)>;
80  using ConstRefSerializedMessageWithInfoCallback =
81  std::function<void (const rclcpp::SerializedMessage &, const rclcpp::MessageInfo &)>;
82 
83  using UniquePtrCallback =
84  std::function<void (std::unique_ptr<SubscribedType, SubscribedMessageDeleter>)>;
85  using UniquePtrROSMessageCallback =
86  std::function<void (std::unique_ptr<ROSMessageType, ROSMessageDeleter>)>;
87  using UniquePtrWithInfoCallback =
88  std::function<void (
89  std::unique_ptr<SubscribedType, SubscribedMessageDeleter>,
90  const rclcpp::MessageInfo &)>;
91  using UniquePtrWithInfoROSMessageCallback =
92  std::function<void (
93  std::unique_ptr<ROSMessageType, ROSMessageDeleter>,
94  const rclcpp::MessageInfo &)>;
95  using UniquePtrSerializedMessageCallback =
96  std::function<void (std::unique_ptr<rclcpp::SerializedMessage, SerializedMessageDeleter>)>;
97  using UniquePtrSerializedMessageWithInfoCallback =
98  std::function<void (
99  std::unique_ptr<rclcpp::SerializedMessage, SerializedMessageDeleter>,
100  const rclcpp::MessageInfo &)>;
101 
102  using SharedConstPtrCallback =
103  std::function<void (std::shared_ptr<const SubscribedType>)>;
104  using SharedConstPtrROSMessageCallback =
105  std::function<void (std::shared_ptr<const ROSMessageType>)>;
106  using SharedConstPtrWithInfoCallback =
107  std::function<void (
108  std::shared_ptr<const SubscribedType>,
109  const rclcpp::MessageInfo &)>;
110  using SharedConstPtrWithInfoROSMessageCallback =
111  std::function<void (
112  std::shared_ptr<const ROSMessageType>,
113  const rclcpp::MessageInfo &)>;
114  using SharedConstPtrSerializedMessageCallback =
115  std::function<void (std::shared_ptr<const rclcpp::SerializedMessage>)>;
116  using SharedConstPtrSerializedMessageWithInfoCallback =
117  std::function<void (
118  std::shared_ptr<const rclcpp::SerializedMessage>,
119  const rclcpp::MessageInfo &)>;
120 
121  using ConstRefSharedConstPtrCallback =
122  std::function<void (const std::shared_ptr<const SubscribedType> &)>;
123  using ConstRefSharedConstPtrROSMessageCallback =
124  std::function<void (const std::shared_ptr<const ROSMessageType> &)>;
125  using ConstRefSharedConstPtrWithInfoCallback =
126  std::function<void (
127  const std::shared_ptr<const SubscribedType> &,
128  const rclcpp::MessageInfo &)>;
129  using ConstRefSharedConstPtrWithInfoROSMessageCallback =
130  std::function<void (
131  const std::shared_ptr<const ROSMessageType> &,
132  const rclcpp::MessageInfo &)>;
133  using ConstRefSharedConstPtrSerializedMessageCallback =
134  std::function<void (const std::shared_ptr<const rclcpp::SerializedMessage> &)>;
135  using ConstRefSharedConstPtrSerializedMessageWithInfoCallback =
136  std::function<void (
137  const std::shared_ptr<const rclcpp::SerializedMessage> &,
138  const rclcpp::MessageInfo &)>;
139 
140  // Deprecated signatures:
141  using SharedPtrCallback =
142  std::function<void (std::shared_ptr<SubscribedType>)>;
143  using SharedPtrROSMessageCallback =
144  std::function<void (std::shared_ptr<ROSMessageType>)>;
145  using SharedPtrWithInfoCallback =
146  std::function<void (std::shared_ptr<SubscribedType>, const rclcpp::MessageInfo &)>;
147  using SharedPtrWithInfoROSMessageCallback =
148  std::function<void (
149  std::shared_ptr<ROSMessageType>,
150  const rclcpp::MessageInfo &)>;
151  using SharedPtrSerializedMessageCallback =
152  std::function<void (std::shared_ptr<rclcpp::SerializedMessage>)>;
153  using SharedPtrSerializedMessageWithInfoCallback =
154  std::function<void (std::shared_ptr<rclcpp::SerializedMessage>, const rclcpp::MessageInfo &)>;
155 };
156 
158 template<
159  typename MessageT,
160  typename AllocatorT,
163 >
165 
167 template<typename MessageT, typename AllocatorT>
168 struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false, false>
169 {
171 
172  using variant_type = std::variant<
173  typename CallbackTypes::ConstRefCallback,
174  typename CallbackTypes::ConstRefWithInfoCallback,
175  typename CallbackTypes::ConstRefSerializedMessageCallback,
176  typename CallbackTypes::ConstRefSerializedMessageWithInfoCallback,
177  typename CallbackTypes::UniquePtrCallback,
178  typename CallbackTypes::UniquePtrWithInfoCallback,
179  typename CallbackTypes::UniquePtrSerializedMessageCallback,
180  typename CallbackTypes::UniquePtrSerializedMessageWithInfoCallback,
181  typename CallbackTypes::SharedConstPtrCallback,
182  typename CallbackTypes::SharedConstPtrWithInfoCallback,
183  typename CallbackTypes::SharedConstPtrSerializedMessageCallback,
184  typename CallbackTypes::SharedConstPtrSerializedMessageWithInfoCallback,
185  typename CallbackTypes::ConstRefSharedConstPtrCallback,
186  typename CallbackTypes::ConstRefSharedConstPtrWithInfoCallback,
187  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageCallback,
188  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageWithInfoCallback,
189  typename CallbackTypes::SharedPtrCallback,
190  typename CallbackTypes::SharedPtrWithInfoCallback,
191  typename CallbackTypes::SharedPtrSerializedMessageCallback,
192  typename CallbackTypes::SharedPtrSerializedMessageWithInfoCallback
193  >;
194 };
195 
197 template<typename MessageT, typename AllocatorT>
198 struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, true, false>
199 {
201 
202  using variant_type = std::variant<
203  typename CallbackTypes::ConstRefCallback,
204  typename CallbackTypes::ConstRefROSMessageCallback,
205  typename CallbackTypes::ConstRefWithInfoCallback,
206  typename CallbackTypes::ConstRefWithInfoROSMessageCallback,
207  typename CallbackTypes::ConstRefSerializedMessageCallback,
208  typename CallbackTypes::ConstRefSerializedMessageWithInfoCallback,
209  typename CallbackTypes::UniquePtrCallback,
210  typename CallbackTypes::UniquePtrROSMessageCallback,
211  typename CallbackTypes::UniquePtrWithInfoCallback,
212  typename CallbackTypes::UniquePtrWithInfoROSMessageCallback,
213  typename CallbackTypes::UniquePtrSerializedMessageCallback,
214  typename CallbackTypes::UniquePtrSerializedMessageWithInfoCallback,
215  typename CallbackTypes::SharedConstPtrCallback,
216  typename CallbackTypes::SharedConstPtrROSMessageCallback,
217  typename CallbackTypes::SharedConstPtrWithInfoCallback,
218  typename CallbackTypes::SharedConstPtrWithInfoROSMessageCallback,
219  typename CallbackTypes::SharedConstPtrSerializedMessageCallback,
220  typename CallbackTypes::SharedConstPtrSerializedMessageWithInfoCallback,
221  typename CallbackTypes::ConstRefSharedConstPtrCallback,
222  typename CallbackTypes::ConstRefSharedConstPtrROSMessageCallback,
223  typename CallbackTypes::ConstRefSharedConstPtrWithInfoCallback,
224  typename CallbackTypes::ConstRefSharedConstPtrWithInfoROSMessageCallback,
225  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageCallback,
226  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageWithInfoCallback,
227  typename CallbackTypes::SharedPtrCallback,
228  typename CallbackTypes::SharedPtrROSMessageCallback,
229  typename CallbackTypes::SharedPtrWithInfoCallback,
230  typename CallbackTypes::SharedPtrWithInfoROSMessageCallback,
231  typename CallbackTypes::SharedPtrSerializedMessageCallback,
232  typename CallbackTypes::SharedPtrSerializedMessageWithInfoCallback
233  >;
234 };
235 
237 template<typename MessageT, typename AllocatorT>
238 struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false, true>
239 {
241 
242  using variant_type = std::variant<
243  typename CallbackTypes::ConstRefSerializedMessageCallback,
244  typename CallbackTypes::ConstRefSerializedMessageWithInfoCallback,
245  typename CallbackTypes::UniquePtrSerializedMessageCallback,
246  typename CallbackTypes::UniquePtrSerializedMessageWithInfoCallback,
247  typename CallbackTypes::SharedConstPtrSerializedMessageCallback,
248  typename CallbackTypes::SharedConstPtrSerializedMessageWithInfoCallback,
249  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageCallback,
250  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageWithInfoCallback,
251  typename CallbackTypes::SharedPtrSerializedMessageCallback,
252  typename CallbackTypes::SharedPtrSerializedMessageWithInfoCallback
253  >;
254 };
255 
256 } // namespace detail
257 
258 template<
259  typename MessageT,
260  typename AllocatorT = std::allocator<void>
261 >
263 {
264 private:
266  using SubscribedType = typename rclcpp::TypeAdapter<MessageT>::custom_type;
268  using ROSMessageType = typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
269 
271 
274  using SubscribedTypeAllocatorTraits = typename SubscribedTypeDeleterHelper::AllocTraits;
275  using SubscribedTypeAllocator = typename SubscribedTypeDeleterHelper::Alloc;
276  using SubscribedTypeDeleter = typename SubscribedTypeDeleterHelper::Deleter;
277 
280  using ROSMessageTypeAllocatorTraits = typename ROSMessageTypeDeleterHelper::AllocTraits;
281  using ROSMessageTypeAllocator = typename ROSMessageTypeDeleterHelper::Alloc;
282  using ROSMessageTypeDeleter = typename ROSMessageTypeDeleterHelper::Deleter;
283 
286  using SerializedMessageAllocatorTraits = typename SerializedMessageDeleterHelper::AllocTraits;
287  using SerializedMessageAllocator = typename SerializedMessageDeleterHelper::Alloc;
288  using SerializedMessageDeleter = typename SerializedMessageDeleterHelper::Deleter;
289 
290  // See AnySubscriptionCallbackPossibleTypes for the types of these.
292 
293  using ConstRefCallback =
294  typename CallbackTypes::ConstRefCallback;
295  using ConstRefROSMessageCallback =
296  typename CallbackTypes::ConstRefROSMessageCallback;
297  using ConstRefWithInfoCallback =
298  typename CallbackTypes::ConstRefWithInfoCallback;
299  using ConstRefWithInfoROSMessageCallback =
300  typename CallbackTypes::ConstRefWithInfoROSMessageCallback;
301  using ConstRefSerializedMessageCallback =
302  typename CallbackTypes::ConstRefSerializedMessageCallback;
303  using ConstRefSerializedMessageWithInfoCallback =
304  typename CallbackTypes::ConstRefSerializedMessageWithInfoCallback;
305  using UniquePtrCallback =
306  typename CallbackTypes::UniquePtrCallback;
307  using UniquePtrROSMessageCallback =
308  typename CallbackTypes::UniquePtrROSMessageCallback;
309  using UniquePtrWithInfoCallback =
310  typename CallbackTypes::UniquePtrWithInfoCallback;
311  using UniquePtrWithInfoROSMessageCallback =
312  typename CallbackTypes::UniquePtrWithInfoROSMessageCallback;
313  using UniquePtrSerializedMessageCallback =
314  typename CallbackTypes::UniquePtrSerializedMessageCallback;
315  using UniquePtrSerializedMessageWithInfoCallback =
316  typename CallbackTypes::UniquePtrSerializedMessageWithInfoCallback;
317  using SharedConstPtrCallback =
318  typename CallbackTypes::SharedConstPtrCallback;
319  using SharedConstPtrROSMessageCallback =
320  typename CallbackTypes::SharedConstPtrROSMessageCallback;
321  using SharedConstPtrWithInfoCallback =
322  typename CallbackTypes::SharedConstPtrWithInfoCallback;
323  using SharedConstPtrWithInfoROSMessageCallback =
324  typename CallbackTypes::SharedConstPtrWithInfoROSMessageCallback;
325  using SharedConstPtrSerializedMessageCallback =
326  typename CallbackTypes::SharedConstPtrSerializedMessageCallback;
327  using SharedConstPtrSerializedMessageWithInfoCallback =
328  typename CallbackTypes::SharedConstPtrSerializedMessageWithInfoCallback;
329  using ConstRefSharedConstPtrCallback =
330  typename CallbackTypes::ConstRefSharedConstPtrCallback;
331  using ConstRefSharedConstPtrROSMessageCallback =
332  typename CallbackTypes::ConstRefSharedConstPtrROSMessageCallback;
333  using ConstRefSharedConstPtrWithInfoCallback =
334  typename CallbackTypes::ConstRefSharedConstPtrWithInfoCallback;
335  using ConstRefSharedConstPtrWithInfoROSMessageCallback =
336  typename CallbackTypes::ConstRefSharedConstPtrWithInfoROSMessageCallback;
337  using ConstRefSharedConstPtrSerializedMessageCallback =
338  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageCallback;
339  using ConstRefSharedConstPtrSerializedMessageWithInfoCallback =
340  typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageWithInfoCallback;
341  using SharedPtrCallback =
342  typename CallbackTypes::SharedPtrCallback;
343  using SharedPtrROSMessageCallback =
344  typename CallbackTypes::SharedPtrROSMessageCallback;
345  using SharedPtrWithInfoCallback =
346  typename CallbackTypes::SharedPtrWithInfoCallback;
347  using SharedPtrWithInfoROSMessageCallback =
348  typename CallbackTypes::SharedPtrWithInfoROSMessageCallback;
349  using SharedPtrSerializedMessageCallback =
350  typename CallbackTypes::SharedPtrSerializedMessageCallback;
351  using SharedPtrSerializedMessageWithInfoCallback =
352  typename CallbackTypes::SharedPtrSerializedMessageWithInfoCallback;
353 
354  template<typename T>
355  struct NotNull
356  {
357  NotNull(const T * pointer_in, const char * msg)
358  : pointer(pointer_in)
359  {
360  if (pointer == nullptr) {
361  throw std::invalid_argument(msg);
362  }
363  }
364 
365  const T * pointer;
366  };
367 
368 public:
369  explicit
370  AnySubscriptionCallback(const AllocatorT & allocator = AllocatorT()) // NOLINT[runtime/explicit]
371  : subscribed_type_allocator_(allocator),
372  ros_message_type_allocator_(allocator)
373  {
374  allocator::set_allocator_for_deleter(&subscribed_type_deleter_, &subscribed_type_allocator_);
375  allocator::set_allocator_for_deleter(&ros_message_type_deleter_, &ros_message_type_allocator_);
376  }
377 
379 
381 
386  template<typename CallbackT>
388  set(CallbackT callback)
389  {
390  // Use the SubscriptionCallbackTypeHelper to determine the actual type of
391  // the CallbackT, in terms of std::function<...>, which does not happen
392  // automatically with lambda functions in cases where the arguments can be
393  // converted to one another, e.g. shared_ptr and unique_ptr.
395 
396  callback_variant_ = static_cast<typename scbth::callback_type>(callback);
397 
398  // Return copy of self for easier testing, normally will be compiled out.
399  return *this;
400  }
401 
402  std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
403  create_ros_unique_ptr_from_ros_shared_ptr_message(
404  const std::shared_ptr<const ROSMessageType> & message)
405  {
406  auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
407  ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr, *message);
408  return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
409  }
410 
411  std::unique_ptr<rclcpp::SerializedMessage, SerializedMessageDeleter>
412  create_serialized_message_unique_ptr_from_shared_ptr(
413  const std::shared_ptr<const rclcpp::SerializedMessage> & serialized_message)
414  {
415  auto ptr = SerializedMessageAllocatorTraits::allocate(serialized_message_allocator_, 1);
416  SerializedMessageAllocatorTraits::construct(
417  serialized_message_allocator_, ptr, *serialized_message);
418  return std::unique_ptr<
420  SerializedMessageDeleter
421  >(ptr, serialized_message_deleter_);
422  }
423 
424  std::unique_ptr<SubscribedType, SubscribedTypeDeleter>
425  create_custom_unique_ptr_from_custom_shared_ptr_message(
426  const std::shared_ptr<const SubscribedType> & message)
427  {
428  auto ptr = SubscribedTypeAllocatorTraits::allocate(subscribed_type_allocator_, 1);
429  SubscribedTypeAllocatorTraits::construct(subscribed_type_allocator_, ptr, *message);
430  return std::unique_ptr<SubscribedType, SubscribedTypeDeleter>(ptr, subscribed_type_deleter_);
431  }
432 
433  std::unique_ptr<SubscribedType, SubscribedTypeDeleter>
434  convert_ros_message_to_custom_type_unique_ptr(const ROSMessageType & msg)
435  {
437  auto ptr = SubscribedTypeAllocatorTraits::allocate(subscribed_type_allocator_, 1);
438  SubscribedTypeAllocatorTraits::construct(subscribed_type_allocator_, ptr);
440  return std::unique_ptr<SubscribedType, SubscribedTypeDeleter>(ptr, subscribed_type_deleter_);
441  } else {
442  throw std::runtime_error(
443  "convert_ros_message_to_custom_type_unique_ptr "
444  "unexpectedly called without TypeAdapter");
445  }
446  }
447 
448  std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
449  convert_custom_type_to_ros_message_unique_ptr(const SubscribedType & msg)
450  {
452  auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
453  ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr);
455  return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
456  } else {
457  static_assert(
458  !sizeof(MessageT *),
459  "convert_custom_type_to_ros_message_unique_ptr() "
460  "unexpectedly called without specialized TypeAdapter");
461  }
462  }
463 
464  // Dispatch when input is a ros message and the output could be anything.
465  template<typename TMsg = ROSMessageType>
466  typename std::enable_if<!serialization_traits::is_serialized_message_class<TMsg>::value,
467  void>::type
468  dispatch(
469  std::shared_ptr<ROSMessageType> message,
470  const rclcpp::MessageInfo & message_info)
471  {
472  TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
473  // Check if the variant is "unset", throw if it is.
474  if (callback_variant_.index() == 0) {
475  if (std::get<0>(callback_variant_) == nullptr) {
476  // This can happen if it is default initialized, or if it is assigned nullptr.
477  throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
478  }
479  }
480  // Dispatch.
481  std::visit(
482  [&message, &message_info, this](auto && callback) {
483  using T = std::decay_t<decltype(callback)>;
484  static constexpr bool is_ta = rclcpp::TypeAdapter<MessageT>::is_specialized::value;
485 
486  // conditions for output is custom message
487  if constexpr (is_ta && std::is_same_v<T, ConstRefCallback>) {
488  // TODO(wjwwood): consider avoiding heap allocation for small messages
489  // maybe something like:
490  // if constexpr (rosidl_generator_traits::has_fixed_size<T> && sizeof(T) < N) {
491  // ... on stack
492  // }
493  auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
494  callback(*local_message);
495  } else if constexpr (is_ta && std::is_same_v<T, ConstRefWithInfoCallback>) { // NOLINT
496  auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
497  callback(*local_message, message_info);
498  } else if constexpr (is_ta && std::is_same_v<T, UniquePtrCallback>) {
499  callback(convert_ros_message_to_custom_type_unique_ptr(*message));
500  } else if constexpr (is_ta && std::is_same_v<T, UniquePtrWithInfoCallback>) {
501  callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
502  } else if constexpr ( // NOLINT[readability/braces]
503  is_ta && (
504  std::is_same_v<T, SharedConstPtrCallback>||
505  std::is_same_v<T, ConstRefSharedConstPtrCallback>||
506  std::is_same_v<T, SharedPtrCallback>
507  ))
508  {
509  callback(convert_ros_message_to_custom_type_unique_ptr(*message));
510  } else if constexpr ( // NOLINT[readability/braces]
511  is_ta && (
512  std::is_same_v<T, SharedConstPtrWithInfoCallback>||
513  std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>||
514  std::is_same_v<T, SharedPtrWithInfoCallback>
515  ))
516  {
517  callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
518  }
519  // conditions for output is ros message
520  else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT
521  callback(*message);
522  } else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) {
523  callback(*message, message_info);
524  } else if constexpr (std::is_same_v<T, UniquePtrROSMessageCallback>) {
525  callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message));
526  } else if constexpr (std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>) {
527  callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message), message_info);
528  } else if constexpr ( // NOLINT[readability/braces]
529  std::is_same_v<T, SharedConstPtrROSMessageCallback>||
530  std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>||
531  std::is_same_v<T, SharedPtrROSMessageCallback>)
532  {
533  callback(message);
534  } else if constexpr ( // NOLINT[readability/braces]
535  std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
536  std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>||
537  std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
538  {
539  callback(message, message_info);
540  }
541  // condition to catch SerializedMessage types
542  else if constexpr ( // NOLINT[readability/braces]
543  std::is_same_v<T, ConstRefSerializedMessageCallback>||
544  std::is_same_v<T, ConstRefSerializedMessageWithInfoCallback>||
545  std::is_same_v<T, UniquePtrSerializedMessageCallback>||
546  std::is_same_v<T, UniquePtrSerializedMessageWithInfoCallback>||
547  std::is_same_v<T, SharedConstPtrSerializedMessageCallback>||
548  std::is_same_v<T, SharedConstPtrSerializedMessageWithInfoCallback>||
549  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageCallback>||
550  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageWithInfoCallback>||
551  std::is_same_v<T, SharedPtrSerializedMessageCallback>||
552  std::is_same_v<T, SharedPtrSerializedMessageWithInfoCallback>)
553  {
554  throw std::runtime_error(
555  "Cannot dispatch std::shared_ptr<ROSMessageType> message "
556  "to rclcpp::SerializedMessage");
557  }
558  // condition to catch unhandled callback types
559  else { // NOLINT[readability/braces]
560  static_assert(detail::always_false_v<T>, "unhandled callback type");
561  }
562  }, callback_variant_);
563  TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
564  }
565 
566  // Dispatch when input is a serialized message and the output could be anything.
567  void
568  dispatch(
569  std::shared_ptr<const rclcpp::SerializedMessage> serialized_message,
570  const rclcpp::MessageInfo & message_info)
571  {
572  TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
573  // Check if the variant is "unset", throw if it is.
574  if (callback_variant_.index() == 0) {
575  if (std::get<0>(callback_variant_) == nullptr) {
576  // This can happen if it is default initialized, or if it is assigned nullptr.
577  throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
578  }
579  }
580  // Dispatch.
581  std::visit(
582  [&serialized_message, &message_info, this](auto && callback) {
583  using T = std::decay_t<decltype(callback)>;
584 
585  // condition to catch SerializedMessage types
586  if constexpr (std::is_same_v<T, ConstRefSerializedMessageCallback>) {
587  callback(*serialized_message);
588  } else if constexpr (std::is_same_v<T, ConstRefSerializedMessageWithInfoCallback>) {
589  callback(*serialized_message, message_info);
590  } else if constexpr (std::is_same_v<T, UniquePtrSerializedMessageCallback>) {
591  callback(create_serialized_message_unique_ptr_from_shared_ptr(serialized_message));
592  } else if constexpr (std::is_same_v<T, UniquePtrSerializedMessageWithInfoCallback>) {
593  callback(
594  create_serialized_message_unique_ptr_from_shared_ptr(serialized_message),
595  message_info);
596  } else if constexpr ( // NOLINT[readability/braces]
597  std::is_same_v<T, SharedConstPtrSerializedMessageCallback>||
598  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageCallback>||
599  std::is_same_v<T, SharedPtrSerializedMessageCallback>)
600  {
601  callback(create_serialized_message_unique_ptr_from_shared_ptr(serialized_message));
602  } else if constexpr ( // NOLINT[readability/braces]
603  std::is_same_v<T, SharedConstPtrSerializedMessageWithInfoCallback>||
604  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageWithInfoCallback>||
605  std::is_same_v<T, SharedPtrSerializedMessageWithInfoCallback>)
606  {
607  callback(
608  create_serialized_message_unique_ptr_from_shared_ptr(serialized_message),
609  message_info);
610  }
611  // conditions for output anything else
612  else if constexpr ( // NOLINT[whitespace/newline]
613  std::is_same_v<T, ConstRefCallback>||
614  std::is_same_v<T, ConstRefROSMessageCallback>||
615  std::is_same_v<T, ConstRefWithInfoCallback>||
616  std::is_same_v<T, ConstRefWithInfoROSMessageCallback>||
617  std::is_same_v<T, UniquePtrCallback>||
618  std::is_same_v<T, UniquePtrROSMessageCallback>||
619  std::is_same_v<T, UniquePtrWithInfoCallback>||
620  std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>||
621  std::is_same_v<T, SharedConstPtrCallback>||
622  std::is_same_v<T, SharedConstPtrROSMessageCallback>||
623  std::is_same_v<T, SharedConstPtrWithInfoCallback>||
624  std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
625  std::is_same_v<T, ConstRefSharedConstPtrCallback>||
626  std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>||
627  std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>||
628  std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>||
629  std::is_same_v<T, SharedPtrCallback>||
630  std::is_same_v<T, SharedPtrROSMessageCallback>||
631  std::is_same_v<T, SharedPtrWithInfoCallback>||
632  std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
633  {
634  throw std::runtime_error(
635  "cannot dispatch rclcpp::SerializedMessage to "
636  "non-rclcpp::SerializedMessage callbacks");
637  }
638  // condition to catch unhandled callback types
639  else { // NOLINT[readability/braces]
640  static_assert(detail::always_false_v<T>, "unhandled callback type");
641  }
642  }, callback_variant_);
643  TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
644  }
645 
646  void
647  dispatch_intra_process(
648  std::shared_ptr<const SubscribedType> message,
649  const rclcpp::MessageInfo & message_info)
650  {
651  TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), true);
652  // Check if the variant is "unset", throw if it is.
653  if (callback_variant_.index() == 0) {
654  if (std::get<0>(callback_variant_) == nullptr) {
655  // This can happen if it is default initialized, or if it is assigned nullptr.
656  throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
657  }
658  }
659  // Dispatch.
660  std::visit(
661  [&message, &message_info, this](auto && callback) {
662  using T = std::decay_t<decltype(callback)>;
663  static constexpr bool is_ta = rclcpp::TypeAdapter<MessageT>::is_specialized::value;
664 
665  // conditions for custom type
666  if constexpr (is_ta && std::is_same_v<T, ConstRefCallback>) {
667  callback(*message);
668  } else if constexpr (is_ta && std::is_same_v<T, ConstRefWithInfoCallback>) { // NOLINT
669  callback(*message, message_info);
670  } else if constexpr ( // NOLINT[readability/braces]
671  is_ta && (
672  std::is_same_v<T, UniquePtrCallback>||
673  std::is_same_v<T, SharedPtrCallback>
674  ))
675  {
676  callback(create_custom_unique_ptr_from_custom_shared_ptr_message(message));
677  } else if constexpr ( // NOLINT[readability/braces]
678  is_ta && (
679  std::is_same_v<T, UniquePtrWithInfoCallback>||
680  std::is_same_v<T, SharedPtrWithInfoCallback>
681  ))
682  {
683  callback(create_custom_unique_ptr_from_custom_shared_ptr_message(message), message_info);
684  } else if constexpr ( // NOLINT[readability/braces]
685  is_ta && (
686  std::is_same_v<T, SharedConstPtrCallback>||
687  std::is_same_v<T, ConstRefSharedConstPtrCallback>
688  ))
689  {
690  callback(message);
691  } else if constexpr ( // NOLINT[readability/braces]
692  is_ta && (
693  std::is_same_v<T, SharedConstPtrWithInfoCallback>||
694  std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>
695  ))
696  {
697  callback(message, message_info);
698  }
699  // conditions for ros message type
700  else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT[readability/braces]
701  if constexpr (is_ta) {
702  auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
703  callback(*local);
704  } else {
705  callback(*message);
706  }
707  } else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) { // NOLINT[readability/braces]
708  if constexpr (is_ta) {
709  auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
710  callback(*local, message_info);
711  } else {
712  callback(*message, message_info);
713  }
714  } else if constexpr ( // NOLINT[readability/braces]
715  std::is_same_v<T, UniquePtrROSMessageCallback>||
716  std::is_same_v<T, SharedPtrROSMessageCallback>)
717  {
718  if constexpr (is_ta) {
719  callback(convert_custom_type_to_ros_message_unique_ptr(*message));
720  } else {
721  callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message));
722  }
723  } else if constexpr ( // NOLINT[readability/braces]
724  std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>||
725  std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
726  {
727  if constexpr (is_ta) {
728  callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
729  } else {
730  callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message), message_info);
731  }
732  } else if constexpr ( // NOLINT[readability/braces]
733  std::is_same_v<T, SharedConstPtrROSMessageCallback>||
734  std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>)
735  {
736  if constexpr (is_ta) {
737  callback(convert_custom_type_to_ros_message_unique_ptr(*message));
738  } else {
739  callback(message);
740  }
741  } else if constexpr ( // NOLINT[readability/braces]
742  std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
743  std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>)
744  {
745  if constexpr (is_ta) {
746  callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
747  } else {
748  callback(message, message_info);
749  }
750  }
751  // condition to catch SerializedMessage types
752  else if constexpr ( // NOLINT[readability/braces]
753  std::is_same_v<T, ConstRefSerializedMessageCallback>||
754  std::is_same_v<T, ConstRefSerializedMessageWithInfoCallback>||
755  std::is_same_v<T, UniquePtrSerializedMessageCallback>||
756  std::is_same_v<T, UniquePtrSerializedMessageWithInfoCallback>||
757  std::is_same_v<T, SharedConstPtrSerializedMessageCallback>||
758  std::is_same_v<T, SharedConstPtrSerializedMessageWithInfoCallback>||
759  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageCallback>||
760  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageWithInfoCallback>||
761  std::is_same_v<T, SharedPtrSerializedMessageCallback>||
762  std::is_same_v<T, SharedPtrSerializedMessageWithInfoCallback>)
763  {
764  throw std::runtime_error(
765  "Cannot dispatch std::shared_ptr<const ROSMessageType> message "
766  "to rclcpp::SerializedMessage");
767  }
768  // condition to catch unhandled callback types
769  else { // NOLINT[readability/braces]
770  static_assert(detail::always_false_v<T>, "unhandled callback type");
771  }
772  }, callback_variant_);
773  TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
774  }
775 
776  void
777  dispatch_intra_process(
778  std::unique_ptr<SubscribedType, SubscribedTypeDeleter> message,
779  const rclcpp::MessageInfo & message_info)
780  {
781  TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), true);
782  // Check if the variant is "unset", throw if it is.
783  if (callback_variant_.index() == 0) {
784  if (std::get<0>(callback_variant_) == nullptr) {
785  // This can happen if it is default initialized, or if it is assigned nullptr.
786  throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
787  }
788  }
789  // Dispatch.
790  std::visit(
791  [&message, &message_info, this](auto && callback) {
792  // clang complains that 'this' lambda capture is unused, which is true
793  // in *some* specializations of this template, but not others. Just
794  // quiet it down.
795  (void)this;
796 
797  using T = std::decay_t<decltype(callback)>;
798  static constexpr bool is_ta = rclcpp::TypeAdapter<MessageT>::is_specialized::value;
799 
800  // conditions for custom type
801  if constexpr (is_ta && std::is_same_v<T, ConstRefCallback>) {
802  callback(*message);
803  } else if constexpr (is_ta && std::is_same_v<T, ConstRefWithInfoCallback>) { // NOLINT
804  callback(*message, message_info);
805  } else if constexpr ( // NOLINT[readability/braces]
806  is_ta && (
807  std::is_same_v<T, UniquePtrCallback>||
808  std::is_same_v<T, SharedPtrCallback>))
809  {
810  callback(std::move(message));
811  } else if constexpr ( // NOLINT[readability/braces]
812  is_ta && (
813  std::is_same_v<T, UniquePtrWithInfoCallback>||
814  std::is_same_v<T, SharedPtrWithInfoCallback>
815  ))
816  {
817  callback(std::move(message), message_info);
818  } else if constexpr ( // NOLINT[readability/braces]
819  is_ta && (
820  std::is_same_v<T, SharedConstPtrCallback>||
821  std::is_same_v<T, ConstRefSharedConstPtrCallback>
822  ))
823  {
824  callback(std::move(message));
825  } else if constexpr ( // NOLINT[readability/braces]
826  is_ta && (
827  std::is_same_v<T, SharedConstPtrWithInfoCallback>||
828  std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>
829  ))
830  {
831  callback(std::move(message), message_info);
832  }
833  // conditions for ros message type
834  else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT[readability/braces]
835  if constexpr (is_ta) {
836  auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
837  callback(*local);
838  } else {
839  callback(*message);
840  }
841  } else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) { // NOLINT[readability/braces]
842  if constexpr (is_ta) {
843  auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
844  callback(*local, message_info);
845  } else {
846  callback(*message, message_info);
847  }
848  } else if constexpr ( // NOLINT[readability/braces]
849  std::is_same_v<T, UniquePtrROSMessageCallback>||
850  std::is_same_v<T, SharedPtrROSMessageCallback>)
851  {
852  if constexpr (is_ta) {
853  callback(convert_custom_type_to_ros_message_unique_ptr(*message));
854  } else {
855  callback(std::move(message));
856  }
857  } else if constexpr ( // NOLINT[readability/braces]
858  std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>||
859  std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
860  {
861  if constexpr (is_ta) {
862  callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
863  } else {
864  callback(std::move(message), message_info);
865  }
866  } else if constexpr ( // NOLINT[readability/braces]
867  std::is_same_v<T, SharedConstPtrROSMessageCallback>||
868  std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>)
869  {
870  if constexpr (is_ta) {
871  callback(convert_custom_type_to_ros_message_unique_ptr(*message));
872  } else {
873  callback(std::move(message));
874  }
875  } else if constexpr ( // NOLINT[readability/braces]
876  std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
877  std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>)
878  {
879  if constexpr (is_ta) {
880  callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
881  } else {
882  callback(std::move(message), message_info);
883  }
884  }
885  // condition to catch SerializedMessage types
886  else if constexpr ( // NOLINT[readability/braces]
887  std::is_same_v<T, ConstRefSerializedMessageCallback>||
888  std::is_same_v<T, ConstRefSerializedMessageWithInfoCallback>||
889  std::is_same_v<T, UniquePtrSerializedMessageCallback>||
890  std::is_same_v<T, UniquePtrSerializedMessageWithInfoCallback>||
891  std::is_same_v<T, SharedConstPtrSerializedMessageCallback>||
892  std::is_same_v<T, SharedConstPtrSerializedMessageWithInfoCallback>||
893  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageCallback>||
894  std::is_same_v<T, ConstRefSharedConstPtrSerializedMessageWithInfoCallback>||
895  std::is_same_v<T, SharedPtrSerializedMessageCallback>||
896  std::is_same_v<T, SharedPtrSerializedMessageWithInfoCallback>)
897  {
898  throw std::runtime_error(
899  "Cannot dispatch std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> message "
900  "to rclcpp::SerializedMessage");
901  }
902  // condition to catch unhandled callback types
903  else { // NOLINT[readability/braces]
904  static_assert(detail::always_false_v<T>, "unhandled callback type");
905  }
906  }, callback_variant_);
907  TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
908  }
909 
910  constexpr
911  bool
912  use_take_shared_method() const
913  {
914  return
915  std::holds_alternative<SharedConstPtrCallback>(callback_variant_) ||
916  std::holds_alternative<SharedConstPtrWithInfoCallback>(callback_variant_) ||
917  std::holds_alternative<ConstRefSharedConstPtrCallback>(callback_variant_) ||
918  std::holds_alternative<ConstRefSharedConstPtrWithInfoCallback>(callback_variant_);
919  }
920 
921  constexpr
922  bool
923  is_serialized_message_callback() const
924  {
925  return
926  std::holds_alternative<ConstRefSerializedMessageCallback>(callback_variant_) ||
927  std::holds_alternative<UniquePtrSerializedMessageCallback>(callback_variant_) ||
928  std::holds_alternative<SharedConstPtrSerializedMessageCallback>(callback_variant_) ||
929  std::holds_alternative<ConstRefSharedConstPtrSerializedMessageCallback>(callback_variant_) ||
930  std::holds_alternative<SharedPtrSerializedMessageCallback>(callback_variant_) ||
931  std::holds_alternative<ConstRefSerializedMessageWithInfoCallback>(callback_variant_) ||
932  std::holds_alternative<UniquePtrSerializedMessageWithInfoCallback>(callback_variant_) ||
933  std::holds_alternative<SharedConstPtrSerializedMessageWithInfoCallback>(callback_variant_) ||
934  std::holds_alternative<ConstRefSharedConstPtrSerializedMessageWithInfoCallback>(
935  callback_variant_) ||
936  std::holds_alternative<SharedPtrSerializedMessageWithInfoCallback>(callback_variant_);
937  }
938 
939  void
940  register_callback_for_tracing()
941  {
942 #ifndef TRACETOOLS_DISABLED
943  std::visit(
944  [this](auto && callback) {
945  if (TRACETOOLS_TRACEPOINT_ENABLED(rclcpp_callback_register)) {
946  char * symbol = tracetools::get_symbol(callback);
947  TRACETOOLS_DO_TRACEPOINT(
948  rclcpp_callback_register,
949  static_cast<const void *>(this),
950  symbol);
951  std::free(symbol);
952  }
953  }, callback_variant_);
954 #endif // TRACETOOLS_DISABLED
955  }
956 
957  typename HelperT::variant_type &
958  get_variant()
959  {
960  return callback_variant_;
961  }
962 
963  const typename HelperT::variant_type &
964  get_variant() const
965  {
966  return callback_variant_;
967  }
968 
969 private:
970  // TODO(wjwwood): switch to inheriting from std::variant (i.e. HelperT::variant_type) once
971  // inheriting from std::variant is realistic (maybe C++23?), see:
972  // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2162r0.html
973  // For now, compose the variant into this class as a private attribute.
974  typename HelperT::variant_type callback_variant_;
975 
976  SubscribedTypeAllocator subscribed_type_allocator_;
977  SubscribedTypeDeleter subscribed_type_deleter_;
978  ROSMessageTypeAllocator ros_message_type_allocator_;
979  ROSMessageTypeDeleter ros_message_type_deleter_;
980  SerializedMessageAllocator serialized_message_allocator_;
981  SerializedMessageDeleter serialized_message_deleter_;
982 };
983 
984 } // namespace rclcpp
985 
986 #endif // RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
AnySubscriptionCallback< MessageT, AllocatorT > set(CallbackT callback)
Generic function for setting the callback.
Additional meta data about messages taken from subscriptions.
Object oriented version of rcl_serialized_message_t with destructor to avoid memory leaks.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
Template structure used to adapt custom, user-defined types to ROS types.
Template helper to select the variant type based on whether or not MessageT is a TypeAdapter.
Struct which contains all possible callback signatures, with or without a TypeAdapter....
typename rclcpp::TypeAdapter< MessageT >::custom_type SubscribedType
MessageT::custom_type if MessageT is a TypeAdapter, otherwise just MessageT.
typename rclcpp::TypeAdapter< MessageT >::ros_message_type ROSMessageType
MessageT::ros_message_type if MessageT is a TypeAdapter, otherwise just MessageT.
Template metaprogramming helper used to resolve the callback argument into a std::function.