Fix missing timer events.

Fixes #6349
This commit is contained in:
Gunnar Beutner 2014-05-28 13:46:39 +02:00
parent 41a9b7d5c0
commit 33cf660c04
2 changed files with 48 additions and 42 deletions

View File

@ -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::member<TimerHolder, Timer::WeakPtr, &TimerHolder::Object> >,
boost::multi_index::ordered_non_unique<boost::multi_index::member<TimerHolder, double, &TimerHolder::Next> >
boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<Timer::Holder, Timer *, &Timer::Holder::GetObject> >,
boost::multi_index::ordered_non_unique<boost::multi_index::const_mem_fun<Timer::Holder, double, &Timer::Holder::GetNextUnlocked> >
>
> 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<TimerSet, 1>::type TimerView;
TimerView& idx = boost::get<1>(l_Timers);
std::vector<Timer::Ptr> timers;
BOOST_FOREACH(const TimerHolder& th, idx) {
Timer::Ptr timer = th.Object.lock();
if (!timer)
continue;
std::vector<Timer *> 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));
}
}

View File

@ -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;
};
}