]> granicus.if.org Git - icinga2/commitdiff
Avoid unnecessary wake-ups for timers.
authorGunnar Beutner <gunnar.beutner@netways.de>
Fri, 22 Jun 2012 09:19:58 +0000 (11:19 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Fri, 22 Jun 2012 09:19:58 +0000 (11:19 +0200)
base/application.cpp
base/timer.cpp
base/timer.h

index 0c75392cac1e50ba3f2c352c44a9faf88d0da2ac..c4e48d8de5703c01f36592b24ad55218dfa0dd48 100644 (file)
@@ -101,7 +101,10 @@ void Application::RunEventLoop(void)
 
                Object::ClearHeldObjects();
 
-               Timer::CallExpiredTimers();
+               long sleep = Timer::ProcessTimers();
+
+               if (m_ShuttingDown)
+                       break;
 
                FD_ZERO(&readfds);
                FD_ZERO(&writefds);
@@ -134,15 +137,8 @@ void Application::RunEventLoop(void)
                                nfds = fd;
                }
 
-               time_t now = time(NULL);
-               time_t next = Timer::GetNextCall();
-               time_t sleep = (next < now) ? 0 : (next - now);
-
-               if (m_ShuttingDown)
-                       break;
-
                timeval tv;
-               tv.tv_sec = (sleep < 0) ? 0 : (long)sleep;
+               tv.tv_sec = sleep;
                tv.tv_usec = 0;
 
                int ready;
index 6efe52aaf423d7ccc666ffda6f81e6d68164c7ee..61ad89c9ce3e350a8547028f507d7771bd8cffcf 100644 (file)
@@ -21,7 +21,6 @@
 
 using namespace icinga;
 
-time_t Timer::NextCall;
 Timer::CollectionType Timer::Timers;
 
 /**
@@ -33,45 +32,13 @@ Timer::Timer(void)
 }
 
 /**
- * Retrieves when the next timer is due.
+ * Calls expired timers and returned when the next wake-up should happen.
  *
  * @returns Time when the next timer is due.
  */
-time_t Timer::GetNextCall(void)
+long Timer::ProcessTimers(void)
 {
-       if (NextCall < time(NULL))
-               Timer::RescheduleTimers();
-
-       return NextCall;
-}
-
-/**
- * Reschedules all timers, thereby updating the NextCall
- * timestamp used by the GetNextCall() function.
- */
-void Timer::RescheduleTimers(void)
-{
-       /* Make sure we wake up at least once every 30 seconds */
-       NextCall = time(NULL) + 30;
-
-       for (Timer::CollectionType::iterator i = Timers.begin(); i != Timers.end(); i++) {
-               Timer::Ptr timer = i->lock();
-
-               if (timer == NULL)
-                       continue;
-
-               if (timer->m_Next < NextCall)
-                       NextCall = timer->m_Next;
-       }
-}
-
-/**
- * Calls all expired timers and reschedules them.
- */
-void Timer::CallExpiredTimers(void)
-{
-       time_t now;
-       time(&now);
+       long wakeup = 30;
 
        Timer::CollectionType::iterator prev, i;
        for (i = Timers.begin(); i != Timers.end(); ) {
@@ -85,11 +52,28 @@ void Timer::CallExpiredTimers(void)
                        continue;
                }
 
+               time_t now;
+               time(&now);
+
                if (timer->m_Next <= now) {
                        timer->Call();
-                       timer->Reschedule(time(NULL) + timer->GetInterval());
+
+                       /* time may have changed depending on how long the
+                        * timer call took - we need to fetch the current time */
+                       time(&now);
+
+                       timer->Reschedule(now + timer->GetInterval());
                }
+
+               assert(timer->m_Next > now);
+
+               if (timer->m_Next - now < wakeup)
+                       wakeup = timer->m_Next - now;
        }
+
+       assert(wakeup > 0);
+
+       return wakeup;
 }
 
 /**
@@ -119,8 +103,11 @@ void Timer::Call(void)
  *
  * @param interval The new interval.
  */
-void Timer::SetInterval(time_t interval)
+void Timer::SetInterval(long interval)
 {
+       if (interval <= 0)
+               throw invalid_argument("interval");
+
        m_Interval = interval;
 }
 
@@ -129,7 +116,7 @@ void Timer::SetInterval(time_t interval)
  *
  * @returns The interval.
  */
-time_t Timer::GetInterval(void) const
+long Timer::GetInterval(void) const
 {
        return m_Interval;
 }
@@ -162,7 +149,4 @@ void Timer::Stop(void)
 void Timer::Reschedule(time_t next)
 {
        m_Next = next;
-
-       if (next < NextCall)
-               NextCall = next;
 }
index 1c00b4ad481a60de3425df28a9c04ce61ee66fb8..651dfe62b5901f78b9f39fb684de5d553c7392ae 100644 (file)
@@ -41,11 +41,10 @@ public:
 
        Timer(void);
 
-       void SetInterval(time_t interval);
-       time_t GetInterval(void) const;
+       void SetInterval(long interval);
+       long GetInterval(void) const;
 
-       static time_t GetNextCall(void);
-       static void CallExpiredTimers(void);
+       static long ProcessTimers(void);
 
        void Start(void);
        void Stop(void);
@@ -55,13 +54,9 @@ public:
        boost::signal<void(const Timer::Ptr&)> OnTimerExpired;
 
 private:
-       time_t m_Interval; /**< The interval of the timer. */
+       long m_Interval; /**< The interval of the timer. */
        time_t m_Next; /**< When the next event should happen. */
 
-       static time_t NextCall; /**< When the next event should happen (for all timers). */
-
-       static void RescheduleTimers(void);
-
        void Call(void);
 };