rclcpp  master
C++ ROS Client Library API
any_subscription_callback.hpp
Go to the documentation of this file.
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 <rmw/types.h>
19 
20 #include <functional>
21 #include <memory>
22 #include <stdexcept>
23 #include <type_traits>
24 #include <utility>
25 
29 #include "tracetools/tracetools.h"
30 #include "tracetools/utils.hpp"
31 
32 namespace rclcpp
33 {
34 
35 template<typename MessageT, typename Alloc>
37 {
38  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
39  using MessageAlloc = typename MessageAllocTraits::allocator_type;
40  using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
43 
53 
54  SharedPtrCallback shared_ptr_callback_;
55  SharedPtrWithInfoCallback shared_ptr_with_info_callback_;
56  ConstSharedPtrCallback const_shared_ptr_callback_;
57  ConstSharedPtrWithInfoCallback const_shared_ptr_with_info_callback_;
58  UniquePtrCallback unique_ptr_callback_;
59  UniquePtrWithInfoCallback unique_ptr_with_info_callback_;
60 
61 public:
63  : shared_ptr_callback_(nullptr), shared_ptr_with_info_callback_(nullptr),
64  const_shared_ptr_callback_(nullptr), const_shared_ptr_with_info_callback_(nullptr),
65  unique_ptr_callback_(nullptr), unique_ptr_with_info_callback_(nullptr)
66  {
67  message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
68  allocator::set_allocator_for_deleter(&message_deleter_, message_allocator_.get());
69  }
70 
72 
73  template<
74  typename CallbackT,
75  typename std::enable_if<
77  CallbackT,
79  >::value
80  >::type * = nullptr
81  >
82  void set(CallbackT callback)
83  {
84  shared_ptr_callback_ = callback;
85  }
86 
87  template<
88  typename CallbackT,
89  typename std::enable_if<
91  CallbackT,
93  >::value
94  >::type * = nullptr
95  >
96  void set(CallbackT callback)
97  {
98  shared_ptr_with_info_callback_ = callback;
99  }
100 
101  template<
102  typename CallbackT,
103  typename std::enable_if<
105  CallbackT,
107  >::value
108  >::type * = nullptr
109  >
110  void set(CallbackT callback)
111  {
112  const_shared_ptr_callback_ = callback;
113  }
114 
115  template<
116  typename CallbackT,
117  typename std::enable_if<
119  CallbackT,
121  >::value
122  >::type * = nullptr
123  >
124  void set(CallbackT callback)
125  {
126  const_shared_ptr_with_info_callback_ = callback;
127  }
128 
129  template<
130  typename CallbackT,
131  typename std::enable_if<
133  CallbackT,
135  >::value
136  >::type * = nullptr
137  >
138  void set(CallbackT callback)
139  {
140  unique_ptr_callback_ = callback;
141  }
142 
143  template<
144  typename CallbackT,
145  typename std::enable_if<
147  CallbackT,
149  >::value
150  >::type * = nullptr
151  >
152  void set(CallbackT callback)
153  {
154  unique_ptr_with_info_callback_ = callback;
155  }
156 
157  void dispatch(
158  std::shared_ptr<MessageT> message, const rmw_message_info_t & message_info)
159  {
160  TRACEPOINT(callback_start, (const void *)this, false);
161  if (shared_ptr_callback_) {
162  shared_ptr_callback_(message);
163  } else if (shared_ptr_with_info_callback_) {
164  shared_ptr_with_info_callback_(message, message_info);
165  } else if (const_shared_ptr_callback_) {
166  const_shared_ptr_callback_(message);
167  } else if (const_shared_ptr_with_info_callback_) {
168  const_shared_ptr_with_info_callback_(message, message_info);
169  } else if (unique_ptr_callback_) {
170  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
171  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *message);
172  unique_ptr_callback_(MessageUniquePtr(ptr, message_deleter_));
173  } else if (unique_ptr_with_info_callback_) {
174  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
175  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *message);
176  unique_ptr_with_info_callback_(MessageUniquePtr(ptr, message_deleter_), message_info);
177  } else {
178  throw std::runtime_error("unexpected message without any callback set");
179  }
180  TRACEPOINT(callback_end, (const void *)this);
181  }
182 
184  ConstMessageSharedPtr message, const rmw_message_info_t & message_info)
185  {
186  TRACEPOINT(callback_start, (const void *)this, true);
187  if (const_shared_ptr_callback_) {
188  const_shared_ptr_callback_(message);
189  } else if (const_shared_ptr_with_info_callback_) {
190  const_shared_ptr_with_info_callback_(message, message_info);
191  } else {
192  if (
193  unique_ptr_callback_ || unique_ptr_with_info_callback_ ||
194  shared_ptr_callback_ || shared_ptr_with_info_callback_)
195  {
196  throw std::runtime_error(
197  "unexpected dispatch_intra_process const shared "
198  "message call with no const shared_ptr callback");
199  } else {
200  throw std::runtime_error("unexpected message without any callback set");
201  }
202  }
203  TRACEPOINT(callback_end, (const void *)this);
204  }
205 
207  MessageUniquePtr message, const rmw_message_info_t & message_info)
208  {
209  TRACEPOINT(callback_start, (const void *)this, true);
210  if (shared_ptr_callback_) {
211  typename std::shared_ptr<MessageT> shared_message = std::move(message);
212  shared_ptr_callback_(shared_message);
213  } else if (shared_ptr_with_info_callback_) {
214  typename std::shared_ptr<MessageT> shared_message = std::move(message);
215  shared_ptr_with_info_callback_(shared_message, message_info);
216  } else if (unique_ptr_callback_) {
217  unique_ptr_callback_(std::move(message));
218  } else if (unique_ptr_with_info_callback_) {
219  unique_ptr_with_info_callback_(std::move(message), message_info);
220  } else if (const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_) {
221  throw std::runtime_error(
222  "unexpected dispatch_intra_process unique message call"
223  " with const shared_ptr callback");
224  } else {
225  throw std::runtime_error("unexpected message without any callback set");
226  }
227  TRACEPOINT(callback_end, (const void *)this);
228  }
229 
231  {
232  return const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_;
233  }
234 
236  {
237  if (shared_ptr_callback_) {
238  TRACEPOINT(
239  rclcpp_callback_register,
240  (const void *)this,
241  get_symbol(shared_ptr_callback_));
242  } else if (shared_ptr_with_info_callback_) {
243  TRACEPOINT(
244  rclcpp_callback_register,
245  (const void *)this,
246  get_symbol(shared_ptr_with_info_callback_));
247  } else if (unique_ptr_callback_) {
248  TRACEPOINT(
249  rclcpp_callback_register,
250  (const void *)this,
251  get_symbol(unique_ptr_callback_));
252  } else if (unique_ptr_with_info_callback_) {
253  TRACEPOINT(
254  rclcpp_callback_register,
255  (const void *)this,
256  get_symbol(unique_ptr_with_info_callback_));
257  }
258  }
259 
260 private:
261  std::shared_ptr<MessageAlloc> message_allocator_;
262  MessageDeleter message_deleter_;
263 };
264 
265 } // namespace rclcpp
266 
267 #endif // RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
bool use_take_shared_method() const
Definition: any_subscription_callback.hpp:230
void dispatch_intra_process(ConstMessageSharedPtr message, const rmw_message_info_t &message_info)
Definition: any_subscription_callback.hpp:183
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
void dispatch_intra_process(MessageUniquePtr message, const rmw_message_info_t &message_info)
Definition: any_subscription_callback.hpp:206
void set_allocator_for_deleter(D *deleter, Alloc *alloc)
Definition: allocator_deleter.hpp:72
AnySubscriptionCallback(std::shared_ptr< Alloc > allocator)
Definition: any_subscription_callback.hpp:62
typename std::allocator_traits< Alloc >::template rebind_traits< T > AllocRebind
Definition: allocator_common.hpp:30
Definition: any_subscription_callback.hpp:36
Definition: function_traits.hpp:161
void register_callback_for_tracing()
Definition: any_subscription_callback.hpp:235
T move(T... args)
T get(T... args)
typename std::conditional< std::is_same< typename std::allocator_traits< Alloc >::template rebind_alloc< T >, typename std::allocator< void >::template rebind< T >::other >::value, std::default_delete< T >, AllocatorDeleter< Alloc > >::type Deleter
Definition: allocator_deleter.hpp:101
void dispatch(std::shared_ptr< MessageT > message, const rmw_message_info_t &message_info)
Definition: any_subscription_callback.hpp:157