mån 2012-12-03 klockan 09:07 -0700 skrev Alex Rousskov:

> Could you please fix this properly by adding
> AsyncEngine::timeTillNextEvent() or similar API and removing loop_delay
> manipulation from checkEvents() as discussed above?

The attached patch adds AsyncEngine::timeTillNextEvent() API. It also
kills the discussed sawActivity loop which imho should not be needed.

The patch is only lightly tested.

Regards
Henrik
=== modified file 'src/AsyncEngine.h'
--- src/AsyncEngine.h	2012-02-05 06:09:46 +0000
+++ src/AsyncEngine.h	2012-12-04 00:06:06 +0000
@@ -71,16 +71,19 @@
      * events.
      *
      * The return value is the status code of the event checking. If its a
-     * non-negative value then it is used as hint for the minimum requested
-     * time before checkEvents is called again. I.e. the event engine knows
-     * how long it is until the next event will be scheduled - so it will
-     * return that time (in milliseconds).
+     * non-negative value then timeTillNextEvent() should be used to check
+     * desired time until next call after other processing have completed.
      *
-     * The timeout value is a requested timeout for this engine - the engine
-     * should not block for more than this period. (If it takes longer than the
-     * timeout to do actual checks thats fine though undesirable).
+     * The timeout value is a requested timeout in msec for this engine - the
+     * engine should not block for more than this period. (If it takes longer
+     * than the timeout to do actual checks thats fine though undesirable).
      */
     virtual int checkEvents(int timeout) = 0;
+
+    /* Returns the desired time in msec until the engine needs to be called
+     * again to continue processing events.
+     */
+    virtual int timeTillNextEvent() = 0;
 };
 
 #endif /* SQUID_ASYNCENGINE_H */

=== modified file 'src/EventLoop.cc'
--- src/EventLoop.cc	2012-02-05 06:09:46 +0000
+++ src/EventLoop.cc	2012-12-03 23:58:00 +0000
@@ -43,17 +43,18 @@
 void
 EventLoop::checkEngine(AsyncEngine * engine, bool const primary)
 {
-    int requested_delay;
+    int rc;
 
     if (!primary)
-        requested_delay = engine->checkEvents(0);
+        rc = engine->checkEvents(0);
     else
-        requested_delay = engine->checkEvents(loop_delay);
+        rc = engine->checkEvents(loop_delay);
 
-    if (requested_delay < 0)
-        switch (requested_delay) {
+    if (rc < 0)
+        switch (rc) {
 
         case AsyncEngine::EVENT_IDLE:
+	    runOnceResult = false;
             debugs(1, 9, "Engine " << engine << " is idle.");
             break;
 
@@ -68,9 +69,6 @@
     else {
         /* not idle or error */
         runOnceResult = false;
-
-        if (requested_delay < loop_delay)
-            loop_delay = requested_delay;
     }
 }
 
@@ -107,19 +105,24 @@
     if (!waitingEngine && !engines.empty())
         waitingEngine = engines.back();
 
-    do {
-        // generate calls and events
-        typedef engine_vector::iterator EVI;
-        for (EVI i = engines.begin(); i != engines.end(); ++i) {
-            if (*i != waitingEngine)
+    // generate calls and events
+    typedef engine_vector::iterator EVI;
+    for (EVI i = engines.begin(); i != engines.end(); ++i) {
+        if (*i != waitingEngine)
                 checkEngine(*i, false);
-        }
-
-        // dispatch calls accumulated so far
-        sawActivity = dispatchCalls();
-        if (sawActivity)
-            runOnceResult = false;
-    } while (sawActivity);
+    }
+
+    // dispatch calls accumulated so far
+    sawActivity = dispatchCalls();
+    if (sawActivity)
+        runOnceResult = false;
+
+    // Figure out how long the waitingEngien is allowed to sleep
+    for (EVI i = engines.begin(); i != engines.end(); ++i) {
+	int requested_timeout = (*i)->timeTillNextEvent();
+	if (requested_timeout >= 0 && loop_delay < requested_timeout)
+		loop_delay = requested_timeout;
+    }
 
     if (waitingEngine != NULL)
         checkEngine(waitingEngine, true);

=== modified file 'src/comm.cc'
--- src/comm.cc	2012-11-26 08:28:09 +0000
+++ src/comm.cc	2012-12-03 23:59:29 +0000
@@ -2086,6 +2086,13 @@
     };
 }
 
+int
+CommSelectEngine::timeTillNextEvent()
+{
+    // We don't know when next event is, so say nothing in particular.
+    return EVENT_IDLE;
+}
+
 /// Create a unix-domain socket (UDS) that only supports FD_MSGHDR I/O.
 int
 comm_open_uds(int sock_type,

=== modified file 'src/comm.h'
--- src/comm.h	2012-02-05 06:09:46 +0000
+++ src/comm.h	2012-12-03 22:51:18 +0000
@@ -107,7 +107,8 @@
 {
 
 public:
-    virtual int checkEvents(int timeout);
+    int checkEvents(int timeout);
+    int timeTillNextEvent();
 };
 
 #endif

=== modified file 'src/event.cc'
--- src/event.cc	2012-02-05 06:09:46 +0000
+++ src/event.cc	2012-12-04 00:03:39 +0000
@@ -242,10 +242,10 @@
     ev_entry *event = NULL;
 
     if (NULL == tasks)
-        return checkDelay();
+        return EVENT_IDLE;
 
     if (tasks->when > current_dtime)
-        return checkDelay();
+        return 0;
 
     PROF_start(eventRun);
 
@@ -274,6 +274,15 @@
     }
 
     PROF_stop(eventRun);
+
+    if (NULL == tasks)
+        return EVENT_IDLE;
+
+    return 0;
+}
+
+int EventScheduler::timeTillNextEvent()
+{
     return checkDelay();
 }
 

=== modified file 'src/event.h'
--- src/event.h	2012-02-05 06:09:46 +0000
+++ src/event.h	2012-12-03 22:50:46 +0000
@@ -93,6 +93,7 @@
     /* schedule a callback function to run in when seconds */
     void schedule(const char *name, EVH * func, void *arg, double when, int weight, bool cbdata=true);
     int checkEvents(int timeout);
+    int timeTillNextEvent();
     static EventScheduler *GetInstance();
 
 private:

=== modified file 'src/main.cc'
--- src/main.cc	2012-11-29 11:20:18 +0000
+++ src/main.cc	2012-12-03 22:57:21 +0000
@@ -190,6 +190,10 @@
         Store::Root().callback();
         return EVENT_IDLE;
     };
+    int timeTillNextEvent() {
+        // TODO: Should this check if there is pending callbacks somehow?
+        return EVENT_IDLE;
+    };
 };
 
 class SignalEngine: public AsyncEngine
@@ -197,7 +201,8 @@
 
 public:
     SignalEngine(EventLoop &evtLoop) : loop(evtLoop) {}
-    virtual int checkEvents(int timeout);
+    int checkEvents(int timeout);
+    int timeTillNextEvent();
 
 private:
     static void StopEventLoop(void * data) {
@@ -233,6 +238,20 @@
     return EVENT_IDLE;
 }
 
+int
+SignalEngine::timeTillNextEvent()
+{
+    if (DebugSignal >= 0)
+	return 0;
+    if (RotateSignal >= 0)
+	return 0;
+    if (ReconfigureSignal >= 0)
+	return 0;
+    if (ShutdownSignal >= 0 )
+	return 0;
+    return EVENT_IDLE;
+}
+
 void
 SignalEngine::doShutdown(time_t wait)
 {

=== modified file 'src/tests/testEventLoop.cc'
--- src/tests/testEventLoop.cc	2012-02-05 06:09:46 +0000
+++ src/tests/testEventLoop.cc	2012-12-04 00:05:36 +0000
@@ -73,6 +73,9 @@
     virtual int checkEvents(int timeout) {
         ++calls;
         lasttimeout = timeout;
+        return 0;
+    }
+    int timeTillNextEvent() {
         return return_timeout;
     }
 };

Reply via email to