Skip to content

Commit f29f89a

Browse files
committed
Remove generation of RCL allocators from C++.
As explained in ros2#1254, there's conceptually no way to implement RCL allocators in terms of C++ allocators. Since allocator_common can't be fixed, delete it and inline calls to rcl_get_default_allocator at the call sites. Since this would introduce surprising behavior for custom allocator users (using system malloc when a custom allocator is requested), add compile-time assertions checking for non-default allocators. Since there's other blocking bugs for allocator use (ros2#1061), this shouldn't break existing users. Technically, we could roll back a lot of templating on allocator and explicitly use std::allocator<void> in all classes. I have refrained from doing so because you might have plans with this code, but if you concur, I'll be more than happy to de-template all these classes to simplify the code.
1 parent 3a4ac0c commit f29f89a

File tree

5 files changed

+17
-80
lines changed

5 files changed

+17
-80
lines changed

rclcpp/include/rclcpp/allocator/allocator_common.hpp

-66
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
#include <memory>
1919

20-
#include "rcl/allocator.h"
21-
2220
#include "rclcpp/allocator/allocator_deleter.hpp"
2321

2422
namespace rclcpp
@@ -29,70 +27,6 @@ namespace allocator
2927
template<typename T, typename Alloc>
3028
using AllocRebind = typename std::allocator_traits<Alloc>::template rebind_traits<T>;
3129

32-
template<typename Alloc>
33-
void * retyped_allocate(size_t size, void * untyped_allocator)
34-
{
35-
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
36-
if (!typed_allocator) {
37-
throw std::runtime_error("Received incorrect allocator type");
38-
}
39-
return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
40-
}
41-
42-
template<typename T, typename Alloc>
43-
void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
44-
{
45-
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
46-
if (!typed_allocator) {
47-
throw std::runtime_error("Received incorrect allocator type");
48-
}
49-
auto typed_ptr = static_cast<T *>(untyped_pointer);
50-
std::allocator_traits<Alloc>::deallocate(*typed_allocator, typed_ptr, 1);
51-
}
52-
53-
template<typename T, typename Alloc>
54-
void * retyped_reallocate(void * untyped_pointer, size_t size, void * untyped_allocator)
55-
{
56-
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
57-
if (!typed_allocator) {
58-
throw std::runtime_error("Received incorrect allocator type");
59-
}
60-
auto typed_ptr = static_cast<T *>(untyped_pointer);
61-
std::allocator_traits<Alloc>::deallocate(*typed_allocator, typed_ptr, 1);
62-
return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
63-
}
64-
65-
66-
// Convert a std::allocator_traits-formatted Allocator into an rcl allocator
67-
template<
68-
typename T,
69-
typename Alloc,
70-
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
71-
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
72-
{
73-
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
74-
#ifndef _WIN32
75-
rcl_allocator.allocate = &retyped_allocate<Alloc>;
76-
rcl_allocator.deallocate = &retyped_deallocate<T, Alloc>;
77-
rcl_allocator.reallocate = &retyped_reallocate<T, Alloc>;
78-
rcl_allocator.state = &allocator;
79-
#else
80-
(void)allocator; // Remove warning
81-
#endif
82-
return rcl_allocator;
83-
}
84-
85-
// TODO(jacquelinekay) Workaround for an incomplete implementation of std::allocator<void>
86-
template<
87-
typename T,
88-
typename Alloc,
89-
typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
90-
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
91-
{
92-
(void)allocator;
93-
return rcl_get_default_allocator();
94-
}
95-
9630
} // namespace allocator
9731
} // namespace rclcpp
9832

rclcpp/include/rclcpp/message_memory_strategy.hpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
#include "rcl/types.h"
2222

23-
#include "rclcpp/allocator/allocator_common.hpp"
23+
#include "rcl/allocator.h"
2424
#include "rclcpp/exceptions.hpp"
2525
#include "rclcpp/macros.hpp"
2626
#include "rclcpp/serialized_message.hpp"
@@ -61,15 +61,19 @@ class MessageMemoryStrategy
6161
message_allocator_ = std::make_shared<MessageAlloc>();
6262
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
6363
buffer_allocator_ = std::make_shared<BufferAlloc>();
64-
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
64+
// The rcl allocator interface is incompatible with C++ allocators
65+
static_assert(std::is_same<Alloc, std::allocator<void>>::value, "Non-default allocators are not supported");
66+
rcutils_allocator_ = rcl_get_default_allocator();
6567
}
6668

6769
explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
6870
{
6971
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
7072
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
7173
buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
72-
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
74+
// The rcl allocator interface is incompatible with C++ allocators
75+
static_assert(std::is_same<Alloc, std::allocator<void>>::value, "Non-default allocators are not supported");
76+
rcutils_allocator_ = rcl_get_default_allocator();
7377
}
7478

7579
virtual ~MessageMemoryStrategy() = default;

rclcpp/include/rclcpp/publisher_options.hpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
#include <string>
2020
#include <vector>
2121

22+
#include "rcl/allocator.h"
2223
#include "rcl/publisher.h"
2324

24-
#include "rclcpp/allocator/allocator_common.hpp"
2525
#include "rclcpp/detail/rmw_implementation_specific_publisher_payload.hpp"
2626
#include "rclcpp/intra_process_setting.hpp"
2727
#include "rclcpp/qos.hpp"
@@ -72,10 +72,9 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
7272
to_rcl_publisher_options(const rclcpp::QoS & qos) const
7373
{
7474
rcl_publisher_options_t result = rcl_publisher_get_default_options();
75-
using AllocatorTraits = std::allocator_traits<Allocator>;
76-
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
77-
auto message_alloc = std::make_shared<MessageAllocatorT>(*this->get_allocator().get());
78-
result.allocator = rclcpp::allocator::get_rcl_allocator<MessageT>(*message_alloc);
75+
// The rcl allocator interface is incompatible with C++ allocators
76+
static_assert(std::is_same<Allocator, std::allocator<void>>::value, "Non-default allocators are not supported");
77+
result.allocator = rcl_get_default_allocator();
7978
result.qos = qos.get_rmw_qos_profile();
8079

8180
// Apply payload to rcl_publisher_options if necessary.

rclcpp/include/rclcpp/strategies/allocator_memory_strategy.hpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
#include "rcl/allocator.h"
2222

23-
#include "rclcpp/allocator/allocator_common.hpp"
2423
#include "rclcpp/memory_strategy.hpp"
2524
#include "rclcpp/node.hpp"
2625
#include "rclcpp/visibility_control.hpp"
@@ -437,7 +436,7 @@ class AllocatorMemoryStrategy : public memory_strategy::MemoryStrategy
437436

438437
rcl_allocator_t get_allocator() override
439438
{
440-
return rclcpp::allocator::get_rcl_allocator<void *, VoidAlloc>(*allocator_.get());
439+
return rcl_get_default_allocator();
441440
}
442441

443442
size_t number_of_ready_subscriptions() const override

rclcpp/include/rclcpp/subscription_options.hpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <string>
2121
#include <vector>
2222

23+
#include "rcl/allocator.h"
24+
2325
#include "rclcpp/callback_group.hpp"
2426
#include "rclcpp/detail/rmw_implementation_specific_subscription_payload.hpp"
2527
#include "rclcpp/intra_process_buffer_type.hpp"
@@ -99,10 +101,9 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
99101
to_rcl_subscription_options(const rclcpp::QoS & qos) const
100102
{
101103
rcl_subscription_options_t result = rcl_subscription_get_default_options();
102-
using AllocatorTraits = std::allocator_traits<Allocator>;
103-
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
104-
auto message_alloc = std::make_shared<MessageAllocatorT>(*allocator.get());
105-
result.allocator = allocator::get_rcl_allocator<MessageT>(*message_alloc);
104+
// The rcl allocator interface is incompatible with C++ allocators
105+
static_assert(std::is_same<Allocator, std::allocator<void>>::value, "Non-default allocators are not supported");
106+
result.allocator = rcl_get_default_allocator();
106107
result.qos = qos.get_rmw_qos_profile();
107108
result.rmw_subscription_options.ignore_local_publications = this->ignore_local_publications;
108109

0 commit comments

Comments
 (0)