Skip to content

Commit 715a983

Browse files
authored
Store graph listener inside the context instead of the node graph (#2952)
* factor shutdown hook registration into its own method Signed-off-by: Skyler Medeiros <[email protected]> * run ament_uncrustify Signed-off-by: Skyler Medeiros <[email protected]> * consistent use of is_shutdown in graph-listener Signed-off-by: Skyler Medeiros <[email protected]> * this doesn't actually need to be a separate function Signed-off-by: Skyler Medeiros <[email protected]> * whitespace Signed-off-by: Skyler Medeiros <[email protected]> * fix typo Signed-off-by: Skyler Medeiros <[email protected]> * move graph listener into the context Signed-off-by: Skyler Medeiros <[email protected]> * make cpplint happy Signed-off-by: Skyler Medeiros <[email protected]> * Update rclcpp/src/rclcpp/context.cpp Signed-off-by: Skyler Medeiros <[email protected]> --------- Signed-off-by: Skyler Medeiros <[email protected]>
1 parent cd9099d commit 715a983

File tree

7 files changed

+63
-37
lines changed

7 files changed

+63
-37
lines changed

rclcpp/include/rclcpp/context.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737

3838
namespace rclcpp
3939
{
40+
namespace graph_listener
41+
{
42+
class GraphListener;
43+
} // namespace graph_listener
4044

4145
/// Thrown when init is called on an already initialized context.
4246
class ContextAlreadyInitialized : public std::runtime_error
@@ -309,6 +313,10 @@ class Context : public std::enable_shared_from_this<Context>
309313
std::shared_ptr<rcl_context_t>
310314
get_rcl_context();
311315

316+
RCLCPP_PUBLIC
317+
std::shared_ptr<rclcpp::graph_listener::GraphListener>
318+
get_graph_listener();
319+
312320
/// Sleep for a given period of time or until shutdown() is called.
313321
/**
314322
* This function can be interrupted early if:
@@ -391,6 +399,9 @@ class Context : public std::enable_shared_from_this<Context>
391399
/// Mutex for protecting the global condition variable.
392400
std::mutex interrupt_mutex_;
393401

402+
/// Graph Listener which waits on graph changes for the node and is shared across nodes.
403+
std::shared_ptr<rclcpp::graph_listener::GraphListener> graph_listener_;
404+
394405
/// Keep shared ownership of global vector of weak contexts
395406
std::shared_ptr<WeakContextsWrapper> weak_contexts_;
396407

rclcpp/include/rclcpp/graph_listener.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ class GraphListener : public std::enable_shared_from_this<GraphListener>
154154
bool
155155
is_shutdown();
156156

157+
/// Return true if the graph listener was started.
158+
RCLCPP_PUBLIC
159+
virtual
160+
bool
161+
is_started();
162+
157163
protected:
158164
/// Main function for the listening thread.
159165
RCLCPP_PUBLIC
@@ -181,7 +187,6 @@ class GraphListener : public std::enable_shared_from_this<GraphListener>
181187
void
182188
__shutdown();
183189

184-
std::weak_ptr<rclcpp::Context> weak_parent_context_;
185190
std::shared_ptr<rcl_context_t> rcl_parent_context_;
186191

187192
std::thread listener_thread_;

rclcpp/include/rclcpp/node_interfaces/node_graph.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,6 @@ class NodeGraph : public NodeGraphInterface
165165
/// Handle to the NodeBaseInterface given in the constructor.
166166
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
167167

168-
/// Graph Listener which waits on graph changes for the node and is shared across nodes.
169-
std::shared_ptr<rclcpp::graph_listener::GraphListener> graph_listener_;
170168
/// Whether or not this node needs to be added to the graph listener.
171169
std::atomic_bool should_add_to_graph_listener_;
172170

rclcpp/src/rclcpp/context.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include "rclcpp/detail/utilities.hpp"
2929
#include "rclcpp/exceptions.hpp"
3030
#include "rclcpp/logging.hpp"
31-
31+
#include "rclcpp/graph_listener.hpp"
3232
#include "rcutils/error_handling.h"
3333
#include "rcutils/macros.h"
3434

@@ -145,7 +145,8 @@ rclcpp_logging_output_handler(
145145
Context::Context()
146146
: rcl_context_(nullptr),
147147
shutdown_reason_(""),
148-
logging_mutex_(nullptr)
148+
logging_mutex_(nullptr),
149+
graph_listener_(nullptr)
149150
{}
150151

151152
Context::~Context()
@@ -243,6 +244,24 @@ Context::init(
243244

244245
weak_contexts_ = get_weak_contexts();
245246
weak_contexts_->add_context(this->shared_from_this());
247+
248+
249+
std::lock_guard<std::recursive_mutex> lock (on_shutdown_callbacks_mutex_);
250+
251+
graph_listener_ = std::make_shared<graph_listener::GraphListener>(shared_from_this());
252+
253+
if (!graph_listener_->is_started()) {
254+
// Register an on_shutdown hook to shutdown the graph listener.
255+
// This is important to ensure that the wait set is finalized before
256+
// destruction of static objects occurs.
257+
std::weak_ptr<rclcpp::graph_listener::GraphListener> weak_graph_listener = graph_listener_;
258+
on_shutdown ([weak_graph_listener]() {
259+
auto shared_graph_listener = weak_graph_listener.lock();
260+
if(shared_graph_listener) {
261+
shared_graph_listener->shutdown(std::nothrow);
262+
}
263+
});
264+
}
246265
} catch (const std::exception & e) {
247266
ret = rcl_shutdown(rcl_context_.get());
248267
rcl_context_.reset();
@@ -500,6 +519,12 @@ Context::get_rcl_context()
500519
return rcl_context_;
501520
}
502521

522+
std::shared_ptr<rclcpp::graph_listener::GraphListener>
523+
Context::get_graph_listener()
524+
{
525+
return graph_listener_;
526+
}
527+
503528
bool
504529
Context::sleep_for(const std::chrono::nanoseconds & nanoseconds)
505530
{

rclcpp/src/rclcpp/graph_listener.cpp

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <memory>
2020
#include <string>
2121
#include <vector>
22-
2322
#include "rcl/error_handling.h"
2423
#include "rcl/types.h"
2524
#include "rclcpp/detail/add_guard_condition_to_rcl_wait_set.hpp"
@@ -38,8 +37,7 @@ namespace graph_listener
3837
{
3938

4039
GraphListener::GraphListener(const std::shared_ptr<Context> & parent_context)
41-
: weak_parent_context_(parent_context),
42-
rcl_parent_context_(parent_context->get_rcl_context()),
40+
: rcl_parent_context_(parent_context->get_rcl_context()),
4341
is_started_(false),
4442
is_shutdown_(false),
4543
interrupt_guard_condition_(parent_context)
@@ -72,23 +70,11 @@ void
7270
GraphListener::start_if_not_started()
7371
{
7472
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
75-
if (is_shutdown_.load()) {
73+
if (is_shutdown()) {
7674
throw GraphListenerShutdownError();
7775
}
78-
auto parent_context = weak_parent_context_.lock();
79-
if (!is_started_ && parent_context) {
80-
// Register an on_shutdown hook to shtudown the graph listener.
81-
// This is important to ensure that the wait set is finalized before
82-
// destruction of static objects occurs.
83-
std::weak_ptr<GraphListener> weak_this = shared_from_this();
84-
parent_context->on_shutdown(
85-
[weak_this]() {
86-
auto shared_this = weak_this.lock();
87-
if (shared_this) {
88-
// should not throw from on_shutdown if it can be avoided
89-
shared_this->shutdown(std::nothrow);
90-
}
91-
});
76+
77+
if (!is_started()) {
9278
// Initialize the wait set before starting.
9379
init_wait_set();
9480
// Start the listener thread.
@@ -122,7 +108,7 @@ GraphListener::run_loop()
122108
{
123109
while (true) {
124110
// If shutdown() was called, exit.
125-
if (is_shutdown_.load()) {
111+
if (is_shutdown()) {
126112
return;
127113
}
128114
rcl_ret_t ret;
@@ -190,7 +176,7 @@ GraphListener::run_loop()
190176
if (graph_gc == wait_set_.guard_conditions[graph_gc_indexes[i]]) {
191177
node_ptr->notify_graph_change();
192178
}
193-
if (is_shutdown_) {
179+
if (is_shutdown()) {
194180
// If shutdown, then notify the node of this as well.
195181
node_ptr->notify_shutdown();
196182
}
@@ -257,7 +243,7 @@ GraphListener::add_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph
257243
throw std::invalid_argument("node is nullptr");
258244
}
259245
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
260-
if (is_shutdown_.load()) {
246+
if (is_shutdown()) {
261247
throw GraphListenerShutdownError();
262248
}
263249

@@ -332,11 +318,11 @@ GraphListener::__shutdown()
332318
{
333319
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
334320
if (!is_shutdown_.exchange(true)) {
335-
if (is_started_) {
321+
if (is_started()) {
336322
interrupt_(&interrupt_guard_condition_);
337323
listener_thread_.join();
338324
}
339-
if (is_started_) {
325+
if (is_started()) {
340326
cleanup_wait_set();
341327
}
342328
}
@@ -365,6 +351,12 @@ GraphListener::shutdown(const std::nothrow_t &) noexcept
365351
}
366352
}
367353

354+
bool
355+
GraphListener::is_started()
356+
{
357+
return is_started_;
358+
}
359+
368360
bool
369361
GraphListener::is_shutdown()
370362
{

rclcpp/src/rclcpp/node_interfaces/node_graph.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ using rclcpp::graph_listener::GraphListener;
3636

3737
NodeGraph::NodeGraph(rclcpp::node_interfaces::NodeBaseInterface * node_base)
3838
: node_base_(node_base),
39-
graph_listener_(
40-
node_base->get_context()->get_sub_context<GraphListener>(node_base->get_context())
41-
),
4239
should_add_to_graph_listener_(true),
4340
graph_users_count_(0)
4441
{}
@@ -50,7 +47,7 @@ NodeGraph::~NodeGraph()
5047
// graph listener after checking that it was not here.
5148
if (!should_add_to_graph_listener_.exchange(false)) {
5249
// If it was already false, then it needs to now be removed.
53-
graph_listener_->remove_node(this);
50+
node_base_->get_context()->get_graph_listener()->remove_node(this);
5451
}
5552
}
5653

@@ -598,8 +595,8 @@ NodeGraph::get_graph_event()
598595
}
599596
// on first call, add node to graph_listener_
600597
if (should_add_to_graph_listener_.exchange(false)) {
601-
graph_listener_->add_node(this);
602-
graph_listener_->start_if_not_started();
598+
node_base_->get_context()->get_graph_listener()->add_node(this);
599+
node_base_->get_context()->get_graph_listener()->start_if_not_started();
603600
}
604601
return event;
605602
}

rclcpp/test/rclcpp/test_graph_listener.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ class TestGraphListener : public ::testing::Test
4343
node_graph_ = node_->get_node_graph_interface();
4444
ASSERT_NE(nullptr, node_graph_);
4545

46-
graph_listener_ =
47-
std::make_shared<rclcpp::graph_listener::GraphListener>(
48-
rclcpp::contexts::get_global_default_context());
46+
graph_listener_ = rclcpp::contexts::get_global_default_context()->get_graph_listener();
4947
}
5048

5149
void TearDown()

0 commit comments

Comments
 (0)