Skip to content

Commit 03163bf

Browse files
alsoraapojomovsky
authored andcommitted
Always trigger guard condition waitset (ros2#1923)
* trigger guard condition waitset regardless of whether a trigger callback is present Signed-off-by: Alberto Soragna <[email protected]> * restore mutex in guard_condition.cpp Signed-off-by: Alberto Soragna <[email protected]> * remove whitespace Signed-off-by: Alberto Soragna <[email protected]> * add unit-test Signed-off-by: Alberto Soragna <[email protected]> * add documentation for trigger and set_on_trigger_callback Signed-off-by: Alberto Soragna <[email protected]>
1 parent a09f6f8 commit 03163bf

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

rclcpp/include/rclcpp/guard_condition.hpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class GuardCondition
7272
const rcl_guard_condition_t &
7373
get_rcl_guard_condition() const;
7474

75-
/// Notify the wait set waiting on this condition, if any, that the condition had been met.
75+
/// Signal that the condition has been met, notifying both the wait set and listeners, if any.
7676
/**
7777
* This function is thread-safe, and may be called concurrently with waiting
7878
* on this guard condition in a wait set.
@@ -107,6 +107,22 @@ class GuardCondition
107107
void
108108
add_to_wait_set(rcl_wait_set_t * wait_set);
109109

110+
/// Set a callback to be called whenever the guard condition is triggered.
111+
/**
112+
* The callback receives a size_t which is the number of times the guard condition was triggered
113+
* since the last time this callback was called.
114+
* Normally this is 1, but can be > 1 if the guard condition was triggered before any
115+
* callback was set.
116+
*
117+
* Calling it again will clear any previously set callback.
118+
*
119+
* This function is thread-safe.
120+
*
121+
* If you want more information available in the callback, like the guard condition
122+
* or other information, you may use a lambda with captures or std::bind.
123+
*
124+
* \param[in] callback functor to be called when the guard condition is triggered
125+
*/
110126
RCLCPP_PUBLIC
111127
void
112128
set_on_trigger_callback(std::function<void(size_t)> callback);

rclcpp/src/rclcpp/guard_condition.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,19 @@ GuardCondition::get_rcl_guard_condition() const
7474
void
7575
GuardCondition::trigger()
7676
{
77-
std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
77+
rcl_ret_t ret = rcl_trigger_guard_condition(&rcl_guard_condition_);
78+
if (RCL_RET_OK != ret) {
79+
rclcpp::exceptions::throw_from_rcl_error(ret);
80+
}
7881

79-
if (on_trigger_callback_) {
80-
on_trigger_callback_(1);
81-
} else {
82-
rcl_ret_t ret = rcl_trigger_guard_condition(&rcl_guard_condition_);
83-
if (RCL_RET_OK != ret) {
84-
rclcpp::exceptions::throw_from_rcl_error(ret);
82+
{
83+
std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
84+
85+
if (on_trigger_callback_) {
86+
on_trigger_callback_(1);
87+
} else {
88+
unread_count_++;
8589
}
86-
unread_count_++;
8790
}
8891
}
8992

@@ -125,10 +128,9 @@ GuardCondition::set_on_trigger_callback(std::function<void(size_t)> callback)
125128
callback(unread_count_);
126129
unread_count_ = 0;
127130
}
128-
return;
131+
} else {
132+
on_trigger_callback_ = nullptr;
129133
}
130-
131-
on_trigger_callback_ = nullptr;
132134
}
133135

134136
} // namespace rclcpp

rclcpp/test/rclcpp/test_guard_condition.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,21 @@ TEST_F(TestGuardCondition, set_on_trigger_callback) {
164164
EXPECT_EQ(c1.load(), 2u);
165165
}
166166
}
167+
168+
/*
169+
* Testing that callback and waitset are both notified by triggering gc
170+
*/
171+
TEST_F(TestGuardCondition, callback_and_waitset) {
172+
auto gc = std::make_shared<rclcpp::GuardCondition>();
173+
std::atomic<size_t> c1 {0};
174+
auto increase_c1_cb = [&c1](size_t count_msgs) {c1 += count_msgs;};
175+
gc->set_on_trigger_callback(increase_c1_cb);
176+
177+
rclcpp::WaitSet wait_set;
178+
wait_set.add_guard_condition(gc);
179+
180+
gc->trigger();
181+
182+
EXPECT_EQ(rclcpp::WaitResultKind::Ready, wait_set.wait(std::chrono::seconds(1)).kind());
183+
EXPECT_EQ(c1.load(), 1u);
184+
}

0 commit comments

Comments
 (0)