rclcpp  master
C++ ROS Client Library API
loaned_message.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__LOANED_MESSAGE_HPP_
16 #define RCLCPP__LOANED_MESSAGE_HPP_
17 
18 #include <memory>
19 #include <utility>
20 
22 #include "rclcpp/logging.hpp"
24 
25 #include "rcl/allocator.h"
26 #include "rcl/publisher.h"
27 
28 namespace rclcpp
29 {
30 
31 template<typename MessageT, typename AllocatorT = std::allocator<void>>
33 {
34  using MessageAllocatorTraits = rclcpp::allocator::AllocRebind<MessageT, AllocatorT>;
35  using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
36 
37 public:
39 
60  const rclcpp::PublisherBase & pub,
61  std::allocator<MessageT> allocator)
62  : pub_(pub),
63  message_(nullptr),
64  message_allocator_(std::move(allocator))
65  {
66  if (pub_.can_loan_messages()) {
67  void * message_ptr = nullptr;
68  auto ret = rcl_borrow_loaned_message(
70  rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
71  &message_ptr);
72  if (RCL_RET_OK != ret) {
74  }
75  message_ = static_cast<MessageT *>(message_ptr);
76  } else {
78  rclcpp::get_logger("rclcpp"),
79  "Currently used middleware can't loan messages. Local allocator will be used.");
80  message_ = message_allocator_.allocate(1);
81  new (message_) MessageT();
82  }
83  }
84 
86 
107  const rclcpp::PublisherBase * pub,
109  : LoanedMessage(*pub, *allocator)
110  {}
111 
114  : pub_(std::move(other.pub_)),
115  message_(std::move(other.message_)),
117  {}
118 
120 
131  virtual ~LoanedMessage()
132  {
133  auto error_logger = rclcpp::get_logger("LoanedMessage");
134 
135  if (message_ == nullptr) {
136  return;
137  }
138 
139  if (pub_.can_loan_messages()) {
140  // return allocated memory to the middleware
141  auto ret =
142  rcl_return_loaned_message_from_publisher(pub_.get_publisher_handle().get(), message_);
143  if (ret != RCL_RET_OK) {
144  RCLCPP_ERROR(
145  error_logger, "rcl_deallocate_loaned_message failed: %s", rcl_get_error_string().str);
146  rcl_reset_error();
147  }
148  } else {
149  // call destructor before deallocating
150  message_->~MessageT();
151  message_allocator_.deallocate(message_, 1);
152  }
153  message_ = nullptr;
154  }
155 
157 
164  bool is_valid() const
165  {
166  return message_ != nullptr;
167  }
168 
170 
177  MessageT & get() const
178  {
179  return *message_;
180  }
181 
183 
189  MessageT * release()
190  {
191  auto msg = message_;
192  message_ = nullptr;
193  return msg;
194  }
195 
196 protected:
198 
199  MessageT * message_;
200 
201  MessageAllocator message_allocator_;
202 
204  LoanedMessage(const LoanedMessage<MessageT> & other) = delete;
205 };
206 
207 } // namespace rclcpp
208 
209 #endif // RCLCPP__LOANED_MESSAGE_HPP_
std::shared_ptr
rclcpp::PublisherBase::get_publisher_handle
std::shared_ptr< rcl_publisher_t > get_publisher_handle()
Get the rcl publisher handle.
rclcpp::LoanedMessage::LoanedMessage
LoanedMessage(LoanedMessage< MessageT > &&other)
Move semantic for RVO.
Definition: loaned_message.hpp:113
rclcpp::get_logger
Logger get_logger(const std::string &name)
Return a named logger.
std::shared_ptr::get
T get(T... args)
rclcpp::LoanedMessage
Definition: loaned_message.hpp:32
rclcpp::LoanedMessage::release
MessageT * release()
Release ownership of the ROS message instance.
Definition: loaned_message.hpp:189
rclcpp::LoanedMessage::message_
MessageT * message_
Definition: loaned_message.hpp:199
rclcpp
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
rclcpp::LoanedMessage::message_allocator_
MessageAllocator message_allocator_
Definition: loaned_message.hpp:201
rclcpp::LoanedMessage::~LoanedMessage
virtual ~LoanedMessage()
Destructor of the LoanedMessage class.
Definition: loaned_message.hpp:131
allocator_common.hpp
logging.hpp
rclcpp::LoanedMessage::is_valid
bool is_valid() const
Validate if the message was correctly allocated.
Definition: loaned_message.hpp:164
rclcpp::allocator::AllocRebind
typename std::allocator_traits< Alloc >::template rebind_traits< T > AllocRebind
Definition: allocator_common.hpp:30
rclcpp::PublisherBase
Definition: publisher_base.hpp:55
rclcpp::LoanedMessage::pub_
const rclcpp::PublisherBase & pub_
Definition: loaned_message.hpp:197
publisher_base.hpp
rclcpp::LoanedMessage::get
MessageT & get() const
Access the ROS message instance.
Definition: loaned_message.hpp:177
std
rclcpp::PublisherBase::can_loan_messages
bool can_loan_messages() const
Check if publisher instance can loan messages.
rclcpp::LoanedMessage::LoanedMessage
LoanedMessage(const rclcpp::PublisherBase &pub, std::allocator< MessageT > allocator)
Constructor of the LoanedMessage class.
Definition: loaned_message.hpp:59
RCLCPP_INFO_ONCE
#define RCLCPP_INFO_ONCE(logger,...)
Definition: logging.hpp:559
std::allocator
rclcpp::exceptions::throw_from_rcl_error
void throw_from_rcl_error(rcl_ret_t ret, const std::string &prefix="", const rcl_error_state_t *error_state=nullptr, void(*reset_error)()=rcl_reset_error)
Throw a C++ std::exception which was created based on an rcl error.
rclcpp::LoanedMessage::LoanedMessage
LoanedMessage(const rclcpp::PublisherBase *pub, std::shared_ptr< std::allocator< MessageT >> allocator)
Constructor of the LoanedMessage class.
Definition: loaned_message.hpp:106
RCLCPP_ERROR
#define RCLCPP_ERROR(logger,...)
Definition: logging.hpp:1419