diff --git a/lib/base/timer.cpp b/lib/base/timer.cpp index 1fac02c0f..203882775 100644 --- a/lib/base/timer.cpp +++ b/lib/base/timer.cpp @@ -31,17 +31,11 @@ using namespace icinga; -struct TimerHolder -{ - Timer::WeakPtr Object; - double Next; -}; - typedef boost::multi_index_container< - TimerHolder, + Timer::Holder, boost::multi_index::indexed_by< - boost::multi_index::ordered_unique >, - boost::multi_index::ordered_non_unique > + boost::multi_index::ordered_unique >, + boost::multi_index::ordered_non_unique > > > TimerSet; @@ -58,6 +52,14 @@ Timer::Timer(void) : m_Interval(0), m_Next(0) { } +/** + * Destructor for the Timer class. + */ +Timer::~Timer(void) +{ + Stop(); +} + /** * Initializes the timer sub-system. */ @@ -153,7 +155,7 @@ void Timer::Stop(void) boost::mutex::scoped_lock lock(l_Mutex); m_Started = false; - l_Timers.erase(GetSelf()); + l_Timers.erase(this); /* Notify the worker thread that we've disabled a timer. */ l_CV.notify_all(); @@ -183,12 +185,8 @@ void Timer::Reschedule(double next) if (m_Started) { /* Remove and re-add the timer to update the index. */ - l_Timers.erase(GetSelf()); - - TimerHolder th; - th.Object = GetSelf(); - th.Next = m_Next; - l_Timers.insert(th); + l_Timers.erase(this); + l_Timers.insert(this); /* Notify the worker that we've rescheduled a timer. */ l_CV.notify_all(); @@ -223,14 +221,9 @@ void Timer::AdjustTimers(double adjustment) typedef boost::multi_index::nth_index::type TimerView; TimerView& idx = boost::get<1>(l_Timers); - std::vector timers; - - BOOST_FOREACH(const TimerHolder& th, idx) { - Timer::Ptr timer = th.Object.lock(); - - if (!timer) - continue; + std::vector timers; + BOOST_FOREACH(Timer *timer, idx) { if (abs(now - (timer->m_Next + adjustment)) < abs(now - timer->m_Next)) { timer->m_Next += adjustment; @@ -238,13 +231,9 @@ void Timer::AdjustTimers(double adjustment) } } - BOOST_FOREACH(const Timer::Ptr& timer, timers) { + BOOST_FOREACH(Timer *timer, timers) { l_Timers.erase(timer); - - TimerHolder th; - th.Object = timer; - th.Next = timer->m_Next; - l_Timers.insert(th); + l_Timers.insert(timer); } /* Notify the worker that we've rescheduled some timers. */ @@ -272,20 +261,11 @@ void Timer::TimerThreadProc(void) break; NextTimerView::iterator it = idx.begin(); - Timer::Ptr timer = it->Object.lock(); - - if (!timer) { - /* Remove the timer from the list if it's not alive anymore. */ - idx.erase(it); - continue; - } + Timer *timer = *it; double wait = timer->m_Next - Utility::GetTime(); if (wait > 0.01) { - /* Make sure the timer we just examined can be destroyed while we're waiting. */ - timer.reset(); - /* Wait for the next timer. */ l_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000)); @@ -296,9 +276,11 @@ void Timer::TimerThreadProc(void) * until the current call is completed. */ l_Timers.erase(timer); + Timer::Ptr ptimer = timer->GetSelf(); + lock.unlock(); /* Asynchronously call the timer. */ - Utility::QueueAsyncCallback(boost::bind(&Timer::Call, timer)); + Utility::QueueAsyncCallback(boost::bind(&Timer::Call, ptimer)); } } diff --git a/lib/base/timer.hpp b/lib/base/timer.hpp index 394ecf69e..8c8550715 100644 --- a/lib/base/timer.hpp +++ b/lib/base/timer.hpp @@ -37,6 +37,7 @@ public: DECLARE_PTR_TYPEDEFS(Timer); Timer(void); + ~Timer(void); void SetInterval(double interval); double GetInterval(void) const; @@ -54,6 +55,31 @@ public: static void Initialize(void); static void Uninitialize(void); + class Holder { + public: + Holder(Timer *timer) + : m_Timer(timer) + { } + + inline Timer *GetObject(void) const + { + return m_Timer; + } + + inline double GetNextUnlocked(void) const + { + return m_Timer->m_Next; + } + + operator Timer *(void) const + { + return m_Timer; + } + + private: + Timer *m_Timer; + }; + private: double m_Interval; /**< The interval of the timer. */ double m_Next; /**< When the next event should happen. */ @@ -62,8 +88,6 @@ private: void Call(); static void TimerThreadProc(void); - - friend struct TimerNextExtractor; }; }