28 #ifndef ROSCPP_TIMER_MANAGER_H 29 #define ROSCPP_TIMER_MANAGER_H 34 #ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC 35 #include <boost/version.hpp> 36 #if BOOST_VERSION < 106100 39 #else // Boost version is 1.61 or greater and has the steady clock fixes 40 #include <boost/thread/condition_variable.hpp> 42 #else // !BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC 43 #include <boost/thread/condition_variable.hpp> 44 #endif // BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC 50 #include <boost/thread/thread.hpp> 51 #include <boost/thread/mutex.hpp> 52 #include <boost/thread/recursive_mutex.hpp> 63 template<
class T,
class D,
class E>
107 void remove(int32_t
handle);
123 void schedule(
const TimerInfoPtr& info);
124 void updateNext(
const TimerInfoPtr& info,
const T& current_time);
149 , last_expected_(last_expected)
150 , last_real_(last_real)
151 , current_expected_(current_expected)
154 boost::mutex::scoped_lock lock(info->waiting_mutex);
155 ++info->waiting_callbacks;
160 TimerInfoPtr info = info_.lock();
163 boost::mutex::scoped_lock lock(info->waiting_mutex);
164 --info->waiting_callbacks;
170 TimerInfoPtr info = info_.lock();
181 if (info->has_tracked_object)
183 tracked = info->tracked_object.lock();
191 event.last_expected = last_expected_;
192 event.last_real = last_real_;
193 event.current_expected = current_expected_;
194 event.current_real = T::now();
195 event.profile.last_duration = info->last_cb_duration;
198 info->callback(event);
200 info->last_cb_duration = cb_end - cb_start;
202 info->last_real =
event.current_real;
204 parent_->schedule(info);
221 template<
class T,
class D,
class E>
228 template<
class T,
class D,
class E>
242 template<
class T,
class D,
class E>
247 if (!infol || !infor)
249 return infol < infor;
252 return infol->next_expected < infor->next_expected;
255 template<
class T,
class D,
class E>
258 typename V_TimerInfo::iterator it =
timers_.begin();
259 typename V_TimerInfo::iterator end =
timers_.end();
260 for (; it != end; ++it)
262 if ((*it)->handle == handle)
271 template<
class T,
class D,
class E>
282 if (info->has_tracked_object)
291 boost::mutex::scoped_lock lock2(info->waiting_mutex);
292 return info->next_expected <= T::now() || info->waiting_callbacks != 0;
295 template<
class T,
class D,
class E>
299 TimerInfoPtr info(boost::make_shared<TimerInfo>());
300 info->period = period;
301 info->callback = callback;
302 info->callback_queue = callback_queue;
303 info->last_expected = T::now();
304 info->next_expected = info->last_expected + period;
305 info->removed =
false;
306 info->has_tracked_object =
false;
307 info->waiting_callbacks = 0;
308 info->total_calls = 0;
309 info->oneshot = oneshot;
312 info->tracked_object = tracked_object;
313 info->has_tracked_object =
true;
317 boost::mutex::scoped_lock lock(
id_mutex_);
344 template<
class T,
class D,
class E>
348 uint64_t remove_id = 0;
353 typename V_TimerInfo::iterator it =
timers_.begin();
354 typename V_TimerInfo::iterator end =
timers_.end();
355 for (; it != end; ++it)
357 const TimerInfoPtr& info = *it;
358 if (info->handle == handle)
360 info->removed =
true;
361 callback_queue = info->callback_queue;
362 remove_id = (uint64_t)info.get();
385 template<
class T,
class D,
class E>
408 template<
class T,
class D,
class E>
413 info->next_expected = T(INT_MAX, 999999999);
420 if (info->next_expected <= current_time)
422 info->last_expected = info->next_expected;
423 info->next_expected += info->period;
427 if (info->next_expected + info->period < current_time)
429 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());
430 info->next_expected = current_time;
435 template<
class T,
class D,
class E>
451 info->next_expected = T::now() + period;
455 else if( (T::now() - info->last_real) < info->period)
459 if( (T::now() - info->last_real) > period)
461 info->next_expected = T::now();
467 info->next_expected = info->last_real + period;
474 info->period = period;
482 template<
class T,
class D,
class E>
493 if (T::now() < current)
499 typename V_TimerInfo::iterator it =
timers_.begin();
500 typename V_TimerInfo::iterator end =
timers_.end();
501 for (; it != end; ++it)
503 const TimerInfoPtr& info = *it;
506 if (current < info->last_expected)
508 info->last_expected = current;
509 info->next_expected = current + info->period;
521 sleep_end = current + D(0.1);
527 while (!
waiting_.empty() && info && info->next_expected <= current)
532 CallbackInterfacePtr cb(boost::make_shared<TimerQueueCallback>(
this, info, info->last_expected, info->last_real, info->next_expected));
533 info->callback_queue->addCallback(cb, (uint64_t)info.get());
547 sleep_end = info->next_expected;
556 if (T::now() < current)
564 if (current >= sleep_end)
571 if (!T::isSystemTime())
573 timers_cond_.timed_wait(lock, boost::posix_time::milliseconds(1));
579 int64_t remaining_time = std::max<int64_t>((sleep_end - current).toSec() * 1000.0f, 1);
580 timers_cond_.timed_wait(lock, boost::posix_time::milliseconds(remaining_time));
void notify_all() BOOST_NOEXCEPT
CallResult
Possible results for the call() method.
boost::function< void(const E &)> callback
void remove(int32_t handle)
std::list< int32_t > L_int32
Abstract interface for items which can be added to a CallbackQueueInterface.
Abstract interface for a queue used to handle all callbacks within roscpp.
TimerManager< T, D, E > * parent_
bool hasPending(int32_t handle)
virtual void removeByID(uint64_t owner_id)=0
Remove all callbacks associated with an owner id.
int32_t add(const D &period, const boost::function< void(const E &)> &callback, CallbackQueueInterface *callback_queue, const VoidConstPtr &tracked_object, bool oneshot)
boost::mutex waiting_mutex
#define ROSCPP_LOG_DEBUG(...)
boost::condition_variable timers_cond_
boost::weak_ptr< void const > VoidConstWPtr
WallDuration last_cb_duration
void updateNext(const TimerInfoPtr &info, const T ¤t_time)
CallbackQueueInterface * callback_queue
CallResult call()
Call this callback.
VoidConstWPtr tracked_object
TimerQueueCallback(TimerManager< T, D, E > *parent, const TimerInfoPtr &info, T last_expected, T last_real, T current_expected)
uint32_t waiting_callbacks
bool waitingCompare(int32_t lhs, int32_t rhs)
boost::weak_ptr< TimerInfo > TimerInfoWPtr
boost::mutex timers_mutex_
boost::shared_ptr< TimerInfo > TimerInfoPtr
std::vector< TimerInfoPtr > V_TimerInfo
static TimerManager & global()
TimerInfoPtr findTimer(int32_t handle)
void notify_one() BOOST_NOEXCEPT
boost::mutex waiting_mutex_
void schedule(const TimerInfoPtr &info)
void setPeriod(int32_t handle, const D &period, bool reset=true)