29 #ifndef ROSCPP_TIMER_MANAGER_H
30 #define ROSCPP_TIMER_MANAGER_H
32 #include "ros/forwards.h"
34 #include "ros/file_log.h"
41 #include "ros/assert.h"
42 #include "ros/callback_queue_interface.h"
50 template<
class T,
class D,
class E>
94 void remove(int32_t handle);
97 void setPeriod(int32_t handle,
const D& period,
bool reset=
true);
141 std::lock_guard<std::mutex> lock(info->waiting_mutex);
142 ++info->waiting_callbacks;
150 std::lock_guard<std::mutex> lock(info->waiting_mutex);
151 --info->waiting_callbacks;
168 if (info->has_tracked_object)
170 tracked = info->tracked_object.lock();
181 event.current_real =
T::now();
182 event.profile.last_duration = info->last_cb_duration;
185 info->callback(event);
187 info->last_cb_duration = cb_end - cb_start;
189 info->last_real =
event.current_real;
208 template<
class T,
class D,
class E>
210 new_timer_(false), id_counter_(0), thread_started_(false), quit_(false)
215 template<
class T,
class D,
class E>
220 std::lock_guard<std::mutex> lock(timers_mutex_);
221 timers_cond_.notify_all();
229 template<
class T,
class D,
class E>
234 if (!infol || !infor)
236 return infol < infor;
239 return infol->next_expected < infor->next_expected;
242 template<
class T,
class D,
class E>
245 typename V_TimerInfo::iterator it = timers_.begin();
246 typename V_TimerInfo::iterator end = timers_.end();
247 for (; it != end; ++it)
249 if ((*it)->handle == handle)
258 template<
class T,
class D,
class E>
261 std::lock_guard<std::mutex> lock(timers_mutex_);
269 if (info->has_tracked_object)
278 std::lock_guard<std::mutex> lock2(info->waiting_mutex);
279 return info->next_expected <=
T::now() || info->waiting_callbacks != 0;
282 template<
class T,
class D,
class E>
287 info->period = period;
289 info->callback_queue = callback_queue;
290 info->last_expected =
T::now();
291 info->next_expected = info->last_expected + period;
292 info->removed =
false;
293 info->has_tracked_object =
false;
294 info->waiting_callbacks = 0;
295 info->total_calls = 0;
296 info->oneshot = oneshot;
299 info->tracked_object = tracked_object;
300 info->has_tracked_object =
true;
304 std::lock_guard<std::mutex> lock(id_mutex_);
305 info->handle = id_counter_++;
309 std::lock_guard<std::mutex> lock(timers_mutex_);
310 timers_.push_back(info);
312 if (!thread_started_)
315 thread_started_ =
true;
319 std::lock_guard<std::mutex> lock(waiting_mutex_);
320 waiting_.push_back(info->handle);
325 timers_cond_.notify_all();
331 template<
class T,
class D,
class E>
335 uint64_t remove_id = 0;
338 std::lock_guard<std::mutex> lock(timers_mutex_);
340 typename V_TimerInfo::iterator it = timers_.begin();
341 typename V_TimerInfo::iterator end = timers_.end();
342 for (; it != end; ++it)
345 if (info->handle == handle)
347 info->removed =
true;
348 callback_queue = info->callback_queue;
349 remove_id = (uint64_t)info.get();
356 std::lock_guard<std::mutex> lock2(waiting_mutex_);
358 L_int32::iterator it = std::find(waiting_.begin(), waiting_.end(), handle);
359 if (it != waiting_.end())
372 template<
class T,
class D,
class E>
375 std::lock_guard<std::mutex> lock(timers_mutex_);
382 updateNext(info,
T::now());
384 std::lock_guard<std::mutex> lock(waiting_mutex_);
386 waiting_.push_back(info->handle);
392 timers_cond_.notify_one();
395 template<
class T,
class D,
class E>
400 info->next_expected = T(INT_MAX, 999999999);
407 if (info->next_expected <= current_time)
409 info->last_expected = info->next_expected;
410 info->next_expected += info->period;
414 if (info->next_expected + info->period < current_time)
416 ROS_DEBUG(
"Time jumped forward by [%f] for timer of period [%f], resetting timer (current=%f, next_expected=%f)", (current_time - info->next_expected).toSec(), info->period.toSec(), current_time.toSec(), info->next_expected.toSec());
417 info->next_expected = current_time;
422 template<
class T,
class D,
class E>
425 std::lock_guard<std::mutex> lock(timers_mutex_);
434 std::lock_guard<std::mutex> lock(waiting_mutex_);
438 info->next_expected =
T::now() + period;
442 else if( (
T::now() - info->last_real) < info->period)
446 if( (
T::now() - info->last_real) > period)
448 info->next_expected =
T::now();
454 info->next_expected = info->last_real + period;
461 info->period = period;
466 timers_cond_.notify_one();
469 template<
class T,
class D,
class E>
477 std::lock_guard<std::mutex> lock(timers_mutex_);
486 typename V_TimerInfo::iterator it = timers_.begin();
487 typename V_TimerInfo::iterator end = timers_.end();
488 for (; it != end; ++it)
493 if (current < info->last_expected)
495 info->last_expected = current;
496 info->next_expected = current + info->period;
504 std::lock_guard<std::mutex> waitlock(waiting_mutex_);
506 if (waiting_.empty())
508 sleep_end = current + D(0.1);
514 while (!waiting_.empty() && info && info->next_expected <= current)
519 CallbackInterfacePtr cb(std::make_shared<TimerQueueCallback>(
this, info, info->last_expected, info->last_real, info->next_expected));
520 info->callback_queue->addCallback(cb, (uint64_t)info.get());
522 waiting_.pop_front();
524 if (waiting_.empty())
529 info = findTimer(waiting_.front());
534 sleep_end = info->next_expected;
539 while (!new_timer_ &&
T::now() < sleep_end && !quit_)
551 if (current >= sleep_end)
558 if (!T::isSystemTime())
560 timers_cond_.timed_wait(lock, std::chrono::milliseconds(1));
566 int32_t remaining_time = std::max((int32_t)((sleep_end - current).toSec() * 1000.0
f), 1);
567 timers_cond_.timed_wait(lock, std::chrono::milliseconds(remaining_time));