Skip to content

Commit 6f6b5f2

Browse files
authored
Stop storing the context in the guard condition. (#2400)
* Stop storing the context in the guard condition. This was creating a circular reference between GuardCondition and Context, so that Context would never be cleaned up. Since we never really need the GuardCondition to know about its own Context, remove that part of the circular reference. While we are in here, we also change the get_context() lambda to a straight weak_ptr; there is no reason for the indirection since the context for the guard condition cannot change at runtime. We also remove the deprecated version of the get_notify_guard_condition(). That's because there is no way to properly implement it in the new scheme, and it seems to be unused outside of rclcpp. Finally, we add in a test that guarantees the use_count is what we expect when inside and leaving a scope, ensuring that contexts will properly be destroyed. Signed-off-by: Chris Lalancette <[email protected]>
1 parent 126d517 commit 6f6b5f2

File tree

7 files changed

+35
-78
lines changed

7 files changed

+35
-78
lines changed

rclcpp/include/rclcpp/callback_group.hpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,15 @@ class CallbackGroup
129129
* added to the executor in either case.
130130
*
131131
* \param[in] group_type The type of the callback group.
132-
* \param[in] get_node_context Lambda to retrieve the node context when
133-
* checking that the creating node is valid and using the guard condition.
132+
* \param[in] context A weak pointer to the context associated with this callback group.
134133
* \param[in] automatically_add_to_executor_with_node A boolean that
135134
* determines whether a callback group is automatically added to an executor
136135
* with the node with which it is associated.
137136
*/
138137
RCLCPP_PUBLIC
139138
explicit CallbackGroup(
140139
CallbackGroupType group_type,
141-
std::function<rclcpp::Context::SharedPtr(void)> get_node_context,
140+
rclcpp::Context::WeakPtr context,
142141
bool automatically_add_to_executor_with_node = true);
143142

144143
/// Default destructor.
@@ -228,16 +227,6 @@ class CallbackGroup
228227
bool
229228
automatically_add_to_executor_with_node() const;
230229

231-
/// Retrieve the guard condition used to signal changes to this callback group.
232-
/**
233-
* \param[in] context_ptr context to use when creating the guard condition
234-
* \return guard condition if it is valid, otherwise nullptr.
235-
*/
236-
[[deprecated("Use get_notify_guard_condition() without arguments")]]
237-
RCLCPP_PUBLIC
238-
rclcpp::GuardCondition::SharedPtr
239-
get_notify_guard_condition(const rclcpp::Context::SharedPtr context_ptr);
240-
241230
/// Retrieve the guard condition used to signal changes to this callback group.
242231
/**
243232
* \return guard condition if it is valid, otherwise nullptr.
@@ -297,7 +286,7 @@ class CallbackGroup
297286
std::shared_ptr<rclcpp::GuardCondition> notify_guard_condition_ = nullptr;
298287
std::recursive_mutex notify_guard_condition_mutex_;
299288

300-
std::function<rclcpp::Context::SharedPtr(void)> get_context_;
289+
rclcpp::Context::WeakPtr context_;
301290

302291
private:
303292
template<typename TypeT, typename Function>

rclcpp/include/rclcpp/guard_condition.hpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class GuardCondition
4848
*/
4949
RCLCPP_PUBLIC
5050
explicit GuardCondition(
51-
rclcpp::Context::SharedPtr context =
51+
const rclcpp::Context::SharedPtr & context =
5252
rclcpp::contexts::get_global_default_context(),
5353
rcl_guard_condition_options_t guard_condition_options =
5454
rcl_guard_condition_get_default_options());
@@ -57,11 +57,6 @@ class GuardCondition
5757
virtual
5858
~GuardCondition();
5959

60-
/// Return the context used when creating this guard condition.
61-
RCLCPP_PUBLIC
62-
rclcpp::Context::SharedPtr
63-
get_context() const;
64-
6560
/// Return the underlying rcl guard condition structure.
6661
RCLCPP_PUBLIC
6762
rcl_guard_condition_t &
@@ -128,7 +123,6 @@ class GuardCondition
128123
set_on_trigger_callback(std::function<void(size_t)> callback);
129124

130125
protected:
131-
rclcpp::Context::SharedPtr context_;
132126
rcl_guard_condition_t rcl_guard_condition_;
133127
std::atomic<bool> in_use_by_wait_set_{false};
134128
std::recursive_mutex reentrant_mutex_;

rclcpp/src/rclcpp/callback_group.cpp

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ using rclcpp::CallbackGroupType;
3131

3232
CallbackGroup::CallbackGroup(
3333
CallbackGroupType group_type,
34-
std::function<rclcpp::Context::SharedPtr(void)> get_context,
34+
rclcpp::Context::WeakPtr context,
3535
bool automatically_add_to_executor_with_node)
3636
: type_(group_type), associated_with_executor_(false),
3737
can_be_taken_from_(true),
3838
automatically_add_to_executor_with_node_(automatically_add_to_executor_with_node),
39-
get_context_(get_context)
39+
context_(context)
4040
{}
4141

4242
CallbackGroup::~CallbackGroup()
@@ -123,40 +123,12 @@ CallbackGroup::automatically_add_to_executor_with_node() const
123123
return automatically_add_to_executor_with_node_;
124124
}
125125

126-
// \TODO(mjcarroll) Deprecated, remove on tock
127-
rclcpp::GuardCondition::SharedPtr
128-
CallbackGroup::get_notify_guard_condition(const rclcpp::Context::SharedPtr context_ptr)
129-
{
130-
std::lock_guard<std::recursive_mutex> lock(notify_guard_condition_mutex_);
131-
if (notify_guard_condition_ && context_ptr != notify_guard_condition_->get_context()) {
132-
if (associated_with_executor_) {
133-
trigger_notify_guard_condition();
134-
}
135-
notify_guard_condition_ = nullptr;
136-
}
137-
138-
if (!notify_guard_condition_) {
139-
notify_guard_condition_ = std::make_shared<rclcpp::GuardCondition>(context_ptr);
140-
}
141-
142-
return notify_guard_condition_;
143-
}
144-
145126
rclcpp::GuardCondition::SharedPtr
146127
CallbackGroup::get_notify_guard_condition()
147128
{
148129
std::lock_guard<std::recursive_mutex> lock(notify_guard_condition_mutex_);
149-
if (!this->get_context_) {
150-
throw std::runtime_error("Callback group was created without context and not passed context");
151-
}
152-
auto context_ptr = this->get_context_();
130+
rclcpp::Context::SharedPtr context_ptr = context_.lock();
153131
if (context_ptr && context_ptr->is_valid()) {
154-
if (notify_guard_condition_ && context_ptr != notify_guard_condition_->get_context()) {
155-
if (associated_with_executor_) {
156-
trigger_notify_guard_condition();
157-
}
158-
notify_guard_condition_ = nullptr;
159-
}
160132
if (!notify_guard_condition_) {
161133
notify_guard_condition_ = std::make_shared<rclcpp::GuardCondition>(context_ptr);
162134
}

rclcpp/src/rclcpp/guard_condition.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@ namespace rclcpp
2323
{
2424

2525
GuardCondition::GuardCondition(
26-
rclcpp::Context::SharedPtr context,
26+
const rclcpp::Context::SharedPtr & context,
2727
rcl_guard_condition_options_t guard_condition_options)
28-
: context_(context), rcl_guard_condition_{rcl_get_zero_initialized_guard_condition()}
28+
: rcl_guard_condition_{rcl_get_zero_initialized_guard_condition()}
2929
{
30-
if (!context_) {
30+
if (!context) {
3131
throw std::invalid_argument("context argument unexpectedly nullptr");
3232
}
33+
3334
rcl_ret_t ret = rcl_guard_condition_init(
3435
&this->rcl_guard_condition_,
35-
context_->get_rcl_context().get(),
36+
context->get_rcl_context().get(),
3637
guard_condition_options);
3738
if (RCL_RET_OK != ret) {
3839
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to create guard condition");
@@ -53,12 +54,6 @@ GuardCondition::~GuardCondition()
5354
}
5455
}
5556

56-
rclcpp::Context::SharedPtr
57-
GuardCondition::get_context() const
58-
{
59-
return context_;
60-
}
61-
6257
rcl_guard_condition_t &
6358
GuardCondition::get_rcl_guard_condition()
6459
{

rclcpp/src/rclcpp/node_interfaces/node_base.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,9 @@ NodeBase::create_callback_group(
218218
rclcpp::CallbackGroupType group_type,
219219
bool automatically_add_to_executor_with_node)
220220
{
221-
auto weak_context = this->get_context()->weak_from_this();
222-
auto get_node_context = [weak_context]() -> rclcpp::Context::SharedPtr {
223-
return weak_context.lock();
224-
};
225-
226221
auto group = std::make_shared<rclcpp::CallbackGroup>(
227222
group_type,
228-
get_node_context,
223+
context_->weak_from_this(),
229224
automatically_add_to_executor_with_node);
230225
std::lock_guard<std::mutex> lock(callback_groups_mutex_);
231226
callback_groups_.push_back(group);

rclcpp/test/rclcpp/test_context.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,25 @@ TEST(TestContext, check_on_shutdown_callback_order_after_del) {
214214

215215
EXPECT_TRUE(result[0] == 1 && result[1] == 3 && result[2] == 4 && result[3] == 0);
216216
}
217+
218+
// This test checks that contexts will be properly destroyed when leaving a scope, after a
219+
// guard condition has been created.
220+
TEST(TestContext, check_context_destroyed) {
221+
rclcpp::Context::SharedPtr ctx;
222+
{
223+
ctx = std::make_shared<rclcpp::Context>();
224+
ctx->init(0, nullptr);
225+
226+
auto group = std::make_shared<rclcpp::CallbackGroup>(
227+
rclcpp::CallbackGroupType::MutuallyExclusive,
228+
ctx->weak_from_this(),
229+
false);
230+
231+
rclcpp::GuardCondition::SharedPtr gc = group->get_notify_guard_condition();
232+
ASSERT_NE(gc, nullptr);
233+
234+
ASSERT_EQ(ctx.use_count(), 1u);
235+
}
236+
237+
ASSERT_EQ(ctx.use_count(), 1u);
238+
}

rclcpp/test/rclcpp/test_guard_condition.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,6 @@ TEST_F(TestGuardCondition, construction_and_destruction) {
6666
}
6767
}
6868

69-
/*
70-
* Testing context accessor.
71-
*/
72-
TEST_F(TestGuardCondition, get_context) {
73-
{
74-
auto gc = std::make_shared<rclcpp::GuardCondition>();
75-
gc->get_context();
76-
}
77-
}
78-
7969
/*
8070
* Testing rcl guard condition accessor.
8171
*/

0 commit comments

Comments
 (0)