Skip to content

Commit 6e22e2f

Browse files
committed
Extend allocator lifetime in options.
Signed-off-by: Steve Wolter <[email protected]>
1 parent 9a59af2 commit 6e22e2f

File tree

2 files changed

+34
-37
lines changed

2 files changed

+34
-37
lines changed

rclcpp/include/rclcpp/publisher_options.hpp

+17-21
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,16 @@ struct PublisherOptionsBase
5656
template<typename Allocator>
5757
struct PublisherOptionsWithAllocator : public PublisherOptionsBase
5858
{
59-
/// Optional custom allocator.
60-
std::shared_ptr<Allocator> allocator = nullptr;
61-
62-
PublisherOptionsWithAllocator<Allocator>() {}
59+
PublisherOptionsWithAllocator<Allocator>()
60+
: allocator_(new Allocator()),
61+
message_allocator_(*allocator_)
62+
{}
6363

6464
/// Constructor using base class as input.
6565
explicit PublisherOptionsWithAllocator(const PublisherOptionsBase & publisher_options_base)
66-
: PublisherOptionsBase(publisher_options_base)
66+
: PublisherOptionsBase(publisher_options_base),
67+
allocator_(new Allocator()),
68+
message_allocator_(*allocator_)
6769
{}
6870

6971
/// Convert this class, and a rclcpp::QoS, into an rcl_publisher_options_t.
@@ -72,12 +74,7 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
7274
to_rcl_publisher_options(const rclcpp::QoS & qos) const
7375
{
7476
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-
// TODO(stevewolter): This is likely to invoke undefined behavior - message_alloc goes
79-
// out of scope at the end of this function, but the allocator doesn't. See #1339.
80-
result.allocator = get_rcl_allocator(*message_alloc);
77+
result.allocator = get_rcl_allocator(message_allocator_);
8178
result.qos = qos.get_rmw_qos_profile();
8279

8380
// Apply payload to rcl_publisher_options if necessary.
@@ -89,20 +86,19 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
8986
}
9087

9188

92-
/// Get the allocator, creating one if needed.
89+
/// Get the allocator
9390
std::shared_ptr<Allocator>
9491
get_allocator() const
9592
{
96-
if (!this->allocator) {
97-
// TODO(wjwwood): I would like to use the commented line instead, but
98-
// cppcheck 1.89 fails with:
99-
// Syntax Error: AST broken, binary operator '>' doesn't have two operands.
100-
// return std::make_shared<Allocator>();
101-
std::shared_ptr<Allocator> tmp(new Allocator());
102-
return tmp;
103-
}
104-
return this->allocator;
93+
return allocator_;
10594
}
95+
96+
private:
97+
using AllocatorTraits = std::allocator_traits<Allocator>;
98+
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
99+
100+
std::shared_ptr<Allocator> allocator_;
101+
MessageAllocatorT message_allocator_;
106102
};
107103

108104
using PublisherOptions = PublisherOptionsWithAllocator<std::allocator<void>>;

rclcpp/include/rclcpp/subscription_options.hpp

+17-16
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,17 @@ struct SubscriptionOptionsBase
7878
template<typename Allocator>
7979
struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
8080
{
81-
/// Optional custom allocator.
82-
std::shared_ptr<Allocator> allocator = nullptr;
83-
84-
SubscriptionOptionsWithAllocator<Allocator>() {}
81+
SubscriptionOptionsWithAllocator<Allocator>()
82+
: allocator_(new Allocator()),
83+
message_allocator_(*allocator_)
84+
{}
8585

8686
/// Constructor using base class as input.
8787
explicit SubscriptionOptionsWithAllocator(
8888
const SubscriptionOptionsBase & subscription_options_base)
89-
: SubscriptionOptionsBase(subscription_options_base)
89+
: SubscriptionOptionsBase(subscription_options_base),
90+
allocator_(new Allocator()),
91+
message_allocator_(*allocator_)
9092
{}
9193

9294
/// Convert this class, with a rclcpp::QoS, into an rcl_subscription_options_t.
@@ -99,12 +101,7 @@ 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-
// TODO(stevewolter): This is likely to invoke undefined behavior - message_alloc
106-
// goes out of scope at the end of this function, but the allocator doesn't. See #1339.
107-
result.allocator = get_rcl_allocator(*message_alloc);
104+
result.allocator = get_rcl_allocator(message_allocator_);
108105
result.qos = qos.get_rmw_qos_profile();
109106
result.rmw_subscription_options.ignore_local_publications = this->ignore_local_publications;
110107

@@ -116,15 +113,19 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
116113
return result;
117114
}
118115

119-
/// Get the allocator, creating one if needed.
116+
/// Get the allocator
120117
std::shared_ptr<Allocator>
121118
get_allocator() const
122119
{
123-
if (!this->allocator) {
124-
return std::make_shared<Allocator>();
125-
}
126-
return this->allocator;
120+
return allocator_
127121
}
122+
123+
private:
124+
using AllocatorTraits = std::allocator_traits<Allocator>;
125+
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
126+
127+
std::shared_ptr<Allocator> allocator_;
128+
MessageAllocatorT message_allocator_;
128129
};
129130

130131
using SubscriptionOptions = SubscriptionOptionsWithAllocator<std::allocator<void>>;

0 commit comments

Comments
 (0)