ROS 2 rclcpp + rcl - kilted  kilted
ROS 2 C++ Client Library with ROS Client Library
intra_process_buffer.hpp
1 // Copyright 2019 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__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
16 #define RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
17 
18 #include <memory>
19 #include <stdexcept>
20 #include <type_traits>
21 #include <utility>
22 #include <vector>
23 
24 #include "rclcpp/allocator/allocator_common.hpp"
25 #include "rclcpp/allocator/allocator_deleter.hpp"
26 #include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
27 #include "rclcpp/macros.hpp"
28 #include "tracetools/tracetools.h"
29 
30 namespace rclcpp
31 {
32 namespace experimental
33 {
34 namespace buffers
35 {
36 
38 {
39 public:
40  RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBufferBase)
41 
42  virtual ~IntraProcessBufferBase() {}
43 
44  virtual void clear() = 0;
45 
46  virtual bool has_data() const = 0;
47  virtual bool use_take_shared_method() const = 0;
48  virtual size_t available_capacity() const = 0;
49 };
50 
51 template<
52  typename MessageT,
53  typename Alloc = std::allocator<void>,
54  typename MessageDeleter = std::default_delete<MessageT>>
56 {
57 public:
58  RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBuffer)
59 
60  virtual ~IntraProcessBuffer() {}
61 
62  using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
63  using MessageSharedPtr = std::shared_ptr<const MessageT>;
64 
65  virtual void add_shared(MessageSharedPtr msg) = 0;
66  virtual void add_unique(MessageUniquePtr msg) = 0;
67 
68  virtual MessageSharedPtr consume_shared() = 0;
69  virtual MessageUniquePtr consume_unique() = 0;
70 
71  virtual std::vector<MessageSharedPtr> get_all_data_shared() = 0;
72  virtual std::vector<MessageUniquePtr> get_all_data_unique() = 0;
73 };
74 
75 template<
76  typename MessageT,
77  typename Alloc = std::allocator<void>,
78  typename MessageDeleter = std::default_delete<MessageT>,
79  typename BufferT = std::unique_ptr<MessageT>>
80 class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, MessageDeleter>
81 {
82 public:
83  RCLCPP_SMART_PTR_DEFINITIONS(TypedIntraProcessBuffer)
84 
85  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
86  using MessageAlloc = typename MessageAllocTraits::allocator_type;
87  using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
88  using MessageSharedPtr = std::shared_ptr<const MessageT>;
89 
90  explicit
92  std::unique_ptr<BufferImplementationBase<BufferT>> buffer_impl,
93  std::shared_ptr<Alloc> allocator = nullptr)
94  {
95  bool valid_type = (std::is_same<BufferT, MessageSharedPtr>::value ||
96  std::is_same<BufferT, MessageUniquePtr>::value);
97  if (!valid_type) {
98  throw std::runtime_error("Creating TypedIntraProcessBuffer with not valid BufferT");
99  }
100 
101  buffer_ = std::move(buffer_impl);
102 
103  TRACETOOLS_TRACEPOINT(
104  rclcpp_buffer_to_ipb,
105  static_cast<const void *>(buffer_.get()),
106  static_cast<const void *>(this));
107  if (!allocator) {
108  message_allocator_ = std::make_shared<MessageAlloc>();
109  } else {
110  message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
111  }
112  }
113 
114  virtual ~TypedIntraProcessBuffer() {}
115 
116  void add_shared(MessageSharedPtr msg) override
117  {
118  add_shared_impl<BufferT>(std::move(msg));
119  }
120 
121  void add_unique(MessageUniquePtr msg) override
122  {
123  buffer_->enqueue(std::move(msg));
124  }
125 
126  MessageSharedPtr consume_shared() override
127  {
128  return consume_shared_impl<BufferT>();
129  }
130 
131  MessageUniquePtr consume_unique() override
132  {
133  return consume_unique_impl<BufferT>();
134  }
135 
136  std::vector<MessageSharedPtr> get_all_data_shared() override
137  {
138  return get_all_data_shared_impl();
139  }
140 
141  std::vector<MessageUniquePtr> get_all_data_unique() override
142  {
143  return get_all_data_unique_impl();
144  }
145 
146  bool has_data() const override
147  {
148  return buffer_->has_data();
149  }
150 
151  void clear() override
152  {
153  buffer_->clear();
154  }
155 
156  bool use_take_shared_method() const override
157  {
158  return std::is_same<BufferT, MessageSharedPtr>::value;
159  }
160 
161  size_t available_capacity() const override
162  {
163  return buffer_->available_capacity();
164  }
165 
166 private:
167  std::unique_ptr<BufferImplementationBase<BufferT>> buffer_;
168 
169  std::shared_ptr<MessageAlloc> message_allocator_;
170 
171  // MessageSharedPtr to MessageSharedPtr
172  template<typename DestinationT>
173  typename std::enable_if<
174  std::is_same<DestinationT, MessageSharedPtr>::value
175  >::type
176  add_shared_impl(MessageSharedPtr shared_msg)
177  {
178  buffer_->enqueue(std::move(shared_msg));
179  }
180 
181  // MessageSharedPtr to MessageUniquePtr
182  template<typename DestinationT>
183  typename std::enable_if<
184  std::is_same<DestinationT, MessageUniquePtr>::value
185  >::type
186  add_shared_impl(MessageSharedPtr shared_msg)
187  {
188  // This should not happen: here a copy is unconditionally made, while the intra-process manager
189  // can decide whether a copy is needed depending on the number and the type of buffers
190 
191  MessageUniquePtr unique_msg;
192  MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
193  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
194  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
195  if (deleter) {
196  unique_msg = MessageUniquePtr(ptr, *deleter);
197  } else {
198  unique_msg = MessageUniquePtr(ptr);
199  }
200 
201  buffer_->enqueue(std::move(unique_msg));
202  }
203 
204  // MessageSharedPtr to MessageSharedPtr
205  template<typename OriginT>
206  typename std::enable_if<
207  std::is_same<OriginT, MessageSharedPtr>::value,
208  MessageSharedPtr
209  >::type
210  consume_shared_impl()
211  {
212  return buffer_->dequeue();
213  }
214 
215  // MessageUniquePtr to MessageSharedPtr
216  template<typename OriginT>
217  typename std::enable_if<
218  (std::is_same<OriginT, MessageUniquePtr>::value),
219  MessageSharedPtr
220  >::type
221  consume_shared_impl()
222  {
223  // automatic cast from unique ptr to shared ptr
224  return buffer_->dequeue();
225  }
226 
227  // MessageSharedPtr to MessageUniquePtr
228  template<typename OriginT>
229  typename std::enable_if<
230  (std::is_same<OriginT, MessageSharedPtr>::value),
231  MessageUniquePtr
232  >::type
233  consume_unique_impl()
234  {
235  MessageSharedPtr buffer_msg = buffer_->dequeue();
236 
237  MessageUniquePtr unique_msg;
238  MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(buffer_msg);
239  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
240  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *buffer_msg);
241  if (deleter) {
242  unique_msg = MessageUniquePtr(ptr, *deleter);
243  } else {
244  unique_msg = MessageUniquePtr(ptr);
245  }
246 
247  return unique_msg;
248  }
249 
250  // MessageUniquePtr to MessageUniquePtr
251  template<typename OriginT>
252  typename std::enable_if<
253  (std::is_same<OriginT, MessageUniquePtr>::value),
254  MessageUniquePtr
255  >::type
256  consume_unique_impl()
257  {
258  return buffer_->dequeue();
259  }
260 
261  // MessageSharedPtr to MessageSharedPtr
262  template<typename T = BufferT>
263  typename std::enable_if<
264  std::is_same<T, MessageSharedPtr>::value,
265  std::vector<MessageSharedPtr>
266  >::type
267  get_all_data_shared_impl()
268  {
269  return buffer_->get_all_data();
270  }
271 
272  // MessageUniquePtr to MessageSharedPtr
273  template<typename T = BufferT>
274  typename std::enable_if<
275  std::is_same<T, MessageUniquePtr>::value,
276  std::vector<MessageSharedPtr>
277  >::type
278  get_all_data_shared_impl()
279  {
280  std::vector<MessageSharedPtr> result;
281  auto uni_ptr_vec = buffer_->get_all_data();
282  result.reserve(uni_ptr_vec.size());
283  for (MessageUniquePtr & uni_ptr : uni_ptr_vec) {
284  result.emplace_back(std::move(uni_ptr));
285  }
286  return result;
287  }
288 
289  // MessageSharedPtr to MessageUniquePtr
290  template<typename T = BufferT>
291  typename std::enable_if<
292  std::is_same<T, MessageSharedPtr>::value,
293  std::vector<MessageUniquePtr>
294  >::type
295  get_all_data_unique_impl()
296  {
297  std::vector<MessageUniquePtr> result;
298  auto shared_ptr_vec = buffer_->get_all_data();
299  result.reserve(shared_ptr_vec.size());
300  for (MessageSharedPtr shared_msg : shared_ptr_vec) {
301  MessageUniquePtr unique_msg;
302  MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
303  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
304  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
305  if (deleter) {
306  unique_msg = MessageUniquePtr(ptr, *deleter);
307  } else {
308  unique_msg = MessageUniquePtr(ptr);
309  }
310  result.push_back(std::move(unique_msg));
311  }
312  return result;
313  }
314 
315  // MessageUniquePtr to MessageUniquePtr
316  template<typename T = BufferT>
317  typename std::enable_if<
318  std::is_same<T, MessageUniquePtr>::value,
319  std::vector<MessageUniquePtr>
320  >::type
321  get_all_data_unique_impl()
322  {
323  return buffer_->get_all_data();
324  }
325 };
326 
327 } // namespace buffers
328 } // namespace experimental
329 } // namespace rclcpp
330 
331 
332 #endif // RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.