ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
allocator_common.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__ALLOCATOR__ALLOCATOR_COMMON_HPP_
16 #define RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
17 
18 #include <cstring>
19 #include <memory>
20 
21 #include "rcl/allocator.h"
22 
23 #include "rclcpp/allocator/allocator_deleter.hpp"
24 
25 namespace rclcpp
26 {
27 namespace allocator
28 {
29 
30 template<typename T>
31 using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
32 
33 // Primary template: false
34 template<typename, typename = std::void_t<>>
35 struct has_get_rcl_allocator : std::false_type {};
36 
37 // Specialization: true if expression is valid
38 template<typename T>
40  std::void_t<
41  decltype(std::declval<clean_t<T> &>().get_rcl_allocator())
42  >
43 >
44  : std::bool_constant<
45  std::is_same_v<
46  decltype(std::declval<clean_t<T> &>().get_rcl_allocator()),
47  rcl_allocator_t
48  >
49  >
50 {};
51 
52 // Helper variable template
53 template<typename T>
54 inline constexpr bool has_get_rcl_allocator_v =
56 
57 template<typename T, typename Alloc>
58 using AllocRebind = typename std::allocator_traits<Alloc>::template rebind_traits<T>;
59 
60 template<typename Alloc>
61 [[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
62  "can not be determined. This will be remove in future versions of ros.")]]
63 void * retyped_allocate(size_t size, void * untyped_allocator)
64 {
65  auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
66  if (!typed_allocator) {
67  throw std::runtime_error("Received incorrect allocator type");
68  }
69  return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
70 }
71 
72 template<typename Alloc>
73 [[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
74  "can not be determined. This will be remove in future versions of ros.")]]
75 void * retyped_zero_allocate(size_t number_of_elem, size_t size_of_elem, void * untyped_allocator)
76 {
77  auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
78  if (!typed_allocator) {
79  throw std::runtime_error("Received incorrect allocator type");
80  }
81  size_t size = number_of_elem * size_of_elem;
82  void * allocated_memory =
83  std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
84  if (allocated_memory) {
85  std::memset(allocated_memory, 0, size);
86  }
87  return allocated_memory;
88 }
89 
90 template<typename T, typename Alloc>
91 [[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
92  "can not be determined. This will be remove in future versions of ros.")]]
93 void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
94 {
95  auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
96  if (!typed_allocator) {
97  throw std::runtime_error("Received incorrect allocator type");
98  }
99  auto typed_ptr = static_cast<T *>(untyped_pointer);
100  std::allocator_traits<Alloc>::deallocate(*typed_allocator, typed_ptr, 1);
101 }
102 
103 template<typename T, typename Alloc>
104 [[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
105  "can not be determined. This will be remove in future versions of ros.")]]
106 void * retyped_reallocate(void * untyped_pointer, size_t size, void * untyped_allocator)
107 {
108  auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
109  if (!typed_allocator) {
110  throw std::runtime_error("Received incorrect allocator type");
111  }
112  auto typed_ptr = static_cast<T *>(untyped_pointer);
113  std::allocator_traits<Alloc>::deallocate(*typed_allocator, typed_ptr, 1);
114  return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
115 }
116 
117 
118 // Convert a std::allocator_traits-formatted Allocator into an rcl allocator
119 template<
120  typename T,
121  typename Alloc,
122  typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
123 [[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
124  "can not be determined. This will be remove in future versions of ros. To suppress this warning"
125  "define the method 'rcl_allocator_t get_rcl_allocator()' on your allocator")]]
126 rcl_allocator_t get_rcl_allocator(Alloc & allocator)
127 {
128  rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
129 #ifndef _WIN32
130  rcl_allocator.allocate = &retyped_allocate<Alloc>;
131  rcl_allocator.zero_allocate = &retyped_zero_allocate<Alloc>;
132  rcl_allocator.deallocate = &retyped_deallocate<T, Alloc>;
133  rcl_allocator.reallocate = &retyped_reallocate<T, Alloc>;
134  rcl_allocator.state = &allocator;
135 #else
136  (void)allocator; // Remove warning
137 #endif
138  return rcl_allocator;
139 }
140 
141 // TODO(jacquelinekay) Workaround for an incomplete implementation of std::allocator<void>
142 template<
143  typename T,
144  typename Alloc,
145  typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
146 rcl_allocator_t get_rcl_allocator(Alloc & allocator)
147 {
148  (void)allocator;
149  return rcl_get_default_allocator();
150 }
151 
152 } // namespace allocator
153 } // namespace rclcpp
154 
155 #endif // RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
Definition: allocator.h:37
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.