rclcpp  master
C++ ROS Client Library API
intra_process_buffer.hpp
Go to the documentation of this file.
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 <type_traits>
20 #include <utility>
21 
25 #include "rclcpp/macros.hpp"
26 
27 namespace rclcpp
28 {
29 namespace experimental
30 {
31 namespace buffers
32 {
33 
35 {
36 public:
38 
39  virtual ~IntraProcessBufferBase() {}
40 
41  virtual void clear() = 0;
42 
43  virtual bool has_data() const = 0;
44  virtual bool use_take_shared_method() const = 0;
45 };
46 
47 template<
48  typename MessageT,
49  typename Alloc = std::allocator<void>,
50  typename MessageDeleter = std::default_delete<MessageT>>
52 {
53 public:
55 
56  virtual ~IntraProcessBuffer() {}
57 
60 
61  virtual void add_shared(MessageSharedPtr msg) = 0;
62  virtual void add_unique(MessageUniquePtr msg) = 0;
63 
64  virtual MessageSharedPtr consume_shared() = 0;
65  virtual MessageUniquePtr consume_unique() = 0;
66 };
67 
68 template<
69  typename MessageT,
70  typename Alloc = std::allocator<void>,
71  typename MessageDeleter = std::default_delete<MessageT>,
72  typename BufferT = std::unique_ptr<MessageT>>
73 class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, MessageDeleter>
74 {
75 public:
77 
78  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
79  using MessageAlloc = typename MessageAllocTraits::allocator_type;
80  using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
81  using MessageSharedPtr = std::shared_ptr<const MessageT>;
82 
83  explicit
85  std::unique_ptr<BufferImplementationBase<BufferT>> buffer_impl,
86  std::shared_ptr<Alloc> allocator = nullptr)
87  {
90  if (!valid_type) {
91  throw std::runtime_error("Creating TypedIntraProcessBuffer with not valid BufferT");
92  }
93 
94  buffer_ = std::move(buffer_impl);
95 
96  if (!allocator) {
97  message_allocator_ = std::make_shared<MessageAlloc>();
98  } else {
99  message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
100  }
101  }
102 
104 
105  void add_shared(MessageSharedPtr msg) override
106  {
107  add_shared_impl<BufferT>(std::move(msg));
108  }
109 
110  void add_unique(MessageUniquePtr msg) override
111  {
112  buffer_->enqueue(std::move(msg));
113  }
114 
116  {
117  return consume_shared_impl<BufferT>();
118  }
119 
121  {
122  return consume_unique_impl<BufferT>();
123  }
124 
125  bool has_data() const override
126  {
127  return buffer_->has_data();
128  }
129 
130  void clear() override
131  {
132  buffer_->clear();
133  }
134 
135  bool use_take_shared_method() const override
136  {
138  }
139 
140 private:
142 
143  std::shared_ptr<MessageAlloc> message_allocator_;
144 
145  // MessageSharedPtr to MessageSharedPtr
146  template<typename DestinationT>
147  typename std::enable_if<
149  >::type
150  add_shared_impl(MessageSharedPtr shared_msg)
151  {
152  buffer_->enqueue(std::move(shared_msg));
153  }
154 
155  // MessageSharedPtr to MessageUniquePtr
156  template<typename DestinationT>
157  typename std::enable_if<
159  >::type
160  add_shared_impl(MessageSharedPtr shared_msg)
161  {
162  // This should not happen: here a copy is unconditionally made, while the intra-process manager
163  // can decide whether a copy is needed depending on the number and the type of buffers
164 
165  MessageUniquePtr unique_msg;
166  MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
167  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
168  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
169  if (deleter) {
170  unique_msg = MessageUniquePtr(ptr, *deleter);
171  } else {
172  unique_msg = MessageUniquePtr(ptr);
173  }
174 
175  buffer_->enqueue(std::move(unique_msg));
176  }
177 
178  // MessageSharedPtr to MessageSharedPtr
179  template<typename OriginT>
180  typename std::enable_if<
183  >::type
184  consume_shared_impl()
185  {
186  return buffer_->dequeue();
187  }
188 
189  // MessageUniquePtr to MessageSharedPtr
190  template<typename OriginT>
191  typename std::enable_if<
194  >::type
195  consume_shared_impl()
196  {
197  // automatic cast from unique ptr to shared ptr
198  return buffer_->dequeue();
199  }
200 
201  // MessageSharedPtr to MessageUniquePtr
202  template<typename OriginT>
203  typename std::enable_if<
204  (std::is_same<OriginT, MessageSharedPtr>::value),
206  >::type
207  consume_unique_impl()
208  {
209  MessageSharedPtr buffer_msg = buffer_->dequeue();
210 
211  MessageUniquePtr unique_msg;
212  MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(buffer_msg);
213  auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
214  MessageAllocTraits::construct(*message_allocator_.get(), ptr, *buffer_msg);
215  if (deleter) {
216  unique_msg = MessageUniquePtr(ptr, *deleter);
217  } else {
218  unique_msg = MessageUniquePtr(ptr);
219  }
220 
221  return unique_msg;
222  }
223 
224  // MessageUniquePtr to MessageUniquePtr
225  template<typename OriginT>
226  typename std::enable_if<
229  >::type
230  consume_unique_impl()
231  {
232  return buffer_->dequeue();
233  }
234 };
235 
236 } // namespace buffers
237 } // namespace experimental
238 } // namespace rclcpp
239 
240 
241 #endif // RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
Definition: intra_process_buffer.hpp:73
void add_unique(MessageUniquePtr msg) override
Definition: intra_process_buffer.hpp:110
bool use_take_shared_method() const override
Definition: intra_process_buffer.hpp:135
#define RCLCPP_SMART_PTR_ALIASES_ONLY(...)
Definition: macros.hpp:66
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
MessageUniquePtr consume_unique() override
Definition: intra_process_buffer.hpp:120
void add_shared(MessageSharedPtr msg) override
Definition: intra_process_buffer.hpp:105
void clear() override
Definition: intra_process_buffer.hpp:130
virtual ~TypedIntraProcessBuffer()
Definition: intra_process_buffer.hpp:103
typename std::allocator_traits< Alloc >::template rebind_traits< T > AllocRebind
Definition: allocator_common.hpp:30
bool has_data() const override
Definition: intra_process_buffer.hpp:125
#define RCLCPP_SMART_PTR_DEFINITIONS(...)
Definition: macros.hpp:36
Definition: intra_process_buffer.hpp:34
MessageSharedPtr consume_shared() override
Definition: intra_process_buffer.hpp:115
allocator::AllocRebind< MessageT, Alloc > MessageAllocTraits
Definition: intra_process_buffer.hpp:78
T move(T... args)
T get(T... args)
Definition: buffer_implementation_base.hpp:26
typename MessageAllocTraits::allocator_type MessageAlloc
Definition: intra_process_buffer.hpp:79
Definition: intra_process_buffer.hpp:51