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