Skip to content

Commit 6764fc9

Browse files
author
iRobot ROS
authored
Merge pull request #55 from mauropasse/mauro/fix-canceled-timer-2
time_until_trigger return MAX if canceled
2 parents 3ae1d43 + 86838ac commit 6764fc9

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

rclcpp/src/rclcpp/executors/timers_manager.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -154,25 +154,30 @@ std::chrono::nanoseconds TimersManager::get_head_timeout_unsafe()
154154
if (weak_timers_heap_.empty()) {
155155
return MAX_TIME;
156156
}
157-
158-
// Weak heap is not empty, so try to lock the first element
159-
TimerPtr head_timer = weak_timers_heap_.front().lock();
157+
// Weak heap is not empty, so try to lock the first element.
160158
// If it is still a valid pointer, it is guaranteed to be the correct head
161-
if (head_timer != nullptr) {
162-
return head_timer->time_until_trigger();
163-
}
159+
TimerPtr head_timer = weak_timers_heap_.front().lock();
164160

165-
// If the first elements has expired, we can't make other assumptions on the heap
166-
// and we need to entirely validate it.
167-
TimersHeap locked_heap = weak_timers_heap_.validate_and_lock();
161+
if (head_timer == nullptr) {
162+
// The first element has expired, we can't make other assumptions on the heap
163+
// and we need to entirely validate it.
164+
TimersHeap locked_heap = weak_timers_heap_.validate_and_lock();
165+
// NOTE: the following operations will not modify any element in the heap, so we
166+
// don't have to call `weak_timers_heap_.store(locked_heap)` at the end.
167+
168+
if (locked_heap.empty()) {
169+
return MAX_TIME;
170+
}
171+
head_timer = locked_heap.front();
172+
}
168173

169-
// NOTE: the following operations will not modify any element in the heap, so we
170-
// don't have to call `weak_timers_heap_.store(locked_heap)` at the end.
174+
auto time_until_trigger = head_timer->time_until_trigger();
171175

172-
if (locked_heap.empty()) {
176+
// A canceled timer will return a nanoseconds::max duration
177+
if (time_until_trigger == std::chrono::nanoseconds::max()) {
173178
return MAX_TIME;
174179
}
175-
return locked_heap.front()->time_until_trigger();
180+
return time_until_trigger;
176181
}
177182

178183
void TimersManager::execute_ready_timers_unsafe()

rclcpp/src/rclcpp/timer.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,16 @@ TimerBase::is_ready()
116116
std::chrono::nanoseconds
117117
TimerBase::time_until_trigger()
118118
{
119+
bool is_canceled = false;
120+
rcl_ret_t ret = rcl_timer_is_canceled(timer_handle_.get(), &is_canceled);
121+
if (ret != RCL_RET_OK) {
122+
rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't get timer cancelled state");
123+
}
124+
if (is_canceled) {
125+
return std::chrono::nanoseconds::max();
126+
}
119127
int64_t time_until_next_call = 0;
120-
rcl_ret_t ret = rcl_timer_get_time_until_next_call(
128+
ret = rcl_timer_get_time_until_next_call(
121129
timer_handle_.get(), &time_until_next_call);
122130
if (ret != RCL_RET_OK) {
123131
rclcpp::exceptions::throw_from_rcl_error(ret, "Timer could not get time until next call");

0 commit comments

Comments
 (0)