ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
message_memory_strategy.hpp
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 #ifndef RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
16 #define RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
17 
18 #include <memory>
19 #include <stdexcept>
20 
21 #include "rcl/allocator.h"
22 #include "rcl/types.h"
23 
24 #include "rclcpp/allocator/allocator_common.hpp"
25 #include "rclcpp/exceptions.hpp"
26 #include "rclcpp/macros.hpp"
27 #include "rclcpp/serialized_message.hpp"
28 #include "rclcpp/visibility_control.hpp"
29 
30 #include "rcutils/logging_macros.h"
31 
32 #include "rmw/serialized_message.h"
33 
34 namespace rclcpp
35 {
36 namespace message_memory_strategy
37 {
38 
40 
41 template<typename MessageT, typename Alloc = std::allocator<void>>
43 {
44 public:
45  RCLCPP_SMART_PTR_DEFINITIONS(MessageMemoryStrategy)
46 
47  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
48  using MessageAlloc = typename MessageAllocTraits::allocator_type;
49  using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
50 
51  using SerializedMessageAllocTraits = allocator::AllocRebind<rclcpp::SerializedMessage, Alloc>;
52  using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
53  using SerializedMessageDeleter =
54  allocator::Deleter<SerializedMessageAlloc, rclcpp::SerializedMessage>;
55 
56  using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
57  using BufferAlloc = typename BufferAllocTraits::allocator_type;
58  using BufferDeleter = allocator::Deleter<BufferAlloc, char>;
59 
61  {
62  message_allocator_ = std::make_shared<MessageAlloc>();
63  serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
64  buffer_allocator_ = std::make_shared<BufferAlloc>();
65  if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
66  rcutils_allocator_ = rcl_get_default_allocator();
67  } else {
68  if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Alloc>) {
69  rcutils_allocator_ = message_allocator_->get_rcl_allocator();
70  } else {
71  rcutils_allocator_ = allocator::get_rcl_allocator<char,
72  BufferAlloc>(*buffer_allocator_.get());
73  }
74  }
75  }
76 
77  explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
78  {
79  message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
80  serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
81  buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
82  if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
83  rcutils_allocator_ = rcl_get_default_allocator();
84  } else {
85  if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Alloc>) {
86  rcutils_allocator_ = allocator->get_rcl_allocator();
87  } else {
88  rcutils_allocator_ = allocator::get_rcl_allocator<char,
89  BufferAlloc>(*buffer_allocator_.get());
90  }
91  }
92  }
93 
94  virtual ~MessageMemoryStrategy() = default;
95 
98  {
99  return std::make_shared<MessageMemoryStrategy<MessageT, Alloc>>(std::make_shared<Alloc>());
100  }
101 
103 
104  virtual std::shared_ptr<MessageT> borrow_message()
105  {
106  return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
107  }
108 
109  virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message(size_t capacity)
110  {
111  return std::make_shared<rclcpp::SerializedMessage>(capacity);
112  }
113 
114  virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message()
115  {
116  return borrow_serialized_message(default_buffer_capacity_);
117  }
118 
119  virtual void set_default_buffer_capacity(size_t capacity)
120  {
121  default_buffer_capacity_ = capacity;
122  }
123 
125 
126  virtual void return_message(std::shared_ptr<MessageT> & msg)
127  {
128  msg.reset();
129  }
130 
131  virtual void return_serialized_message(
132  std::shared_ptr<rclcpp::SerializedMessage> & serialized_msg)
133  {
134  serialized_msg.reset();
135  }
136 
137  std::shared_ptr<MessageAlloc> message_allocator_;
138  MessageDeleter message_deleter_;
139 
140  std::shared_ptr<SerializedMessageAlloc> serialized_message_allocator_;
141  SerializedMessageDeleter serialized_message_deleter_;
142 
143  std::shared_ptr<BufferAlloc> buffer_allocator_;
144  BufferDeleter buffer_deleter_;
145  size_t default_buffer_capacity_ = 0;
146 
147  rcutils_allocator_t rcutils_allocator_;
148 };
149 
150 } // namespace message_memory_strategy
151 } // namespace rclcpp
152 
153 #endif // RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
Definition: allocator.h:37
Default allocation strategy for messages received by subscriptions.
static SharedPtr create_default()
Default factory method.
virtual void return_message(std::shared_ptr< MessageT > &msg)
Release ownership of the message, which will deallocate it if it has no more owners.
virtual std::shared_ptr< MessageT > borrow_message()
By default, dynamically allocate a new message.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
@ SharedPtr
Set the data type used in the intra-process buffer as std::shared_ptr<MessageT>