diff --git a/configure.ac b/configure.ac index 605cea996f9..4ee76fd089b 100644 --- a/configure.ac +++ b/configure.ac @@ -2578,6 +2578,7 @@ AC_CONFIG_FILES([ src/DiskIO/DiskThreads/Makefile src/DiskIO/IpcIo/Makefile src/DiskIO/Mmapped/Makefile + src/engines/Makefile src/error/Makefile src/eui/Makefile src/format/Makefile diff --git a/src/EventLoop.h b/src/EventLoop.h deleted file mode 100644 index d80b2420e08..00000000000 --- a/src/EventLoop.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 1996-2026 The Squid Software Foundation and contributors - * - * Squid software is distributed under GPLv2+ license and includes - * contributions from numerous individuals and organizations. - * Please see the COPYING and CONTRIBUTORS files for details. - */ - -#ifndef SQUID_SRC_EVENTLOOP_H -#define SQUID_SRC_EVENTLOOP_H - -#include "time/forward.h" - -#include - -#define EVENT_LOOP_TIMEOUT 1000 /* 1s timeout */ - -class AsyncEngine; - -/** An event loop. An event loop is the core inner loop of squid. - * The event loop can be run until exit, or once. After it finishes control - * returns to the caller. If desired it can be run again. - \par - * The event loop cannot be run once it is running until it has finished. - */ -class EventLoop -{ - -public: - EventLoop(); - - /** register an async engine which will be given the opportunity to perform - * in-main-thread tasks each event loop. - */ - void registerEngine(AsyncEngine *engine); - - /** start the event loop running. The loop will run until it is stopped by - * calling stop(), or when the loop is completely idle - nothing - * dispatched in a loop, and all engines idle. - */ - void run(); - - /** run the loop once. This may not complete all events! It should therefor - * be used with care. - * TODO: signal in runOnce whether or not the loop is over - IDLE vs OK vs - * TIMEOUT? - */ - bool runOnce(); - - /** set the primary async engine. The primary async engine receives the - * lowest requested timeout gathered from the other engines each loop. - * (There is a default of 10ms if all engines are idle or request higher - * delays). - * If no primary has been nominated, the last async engine added is - * implicitly the default. - */ - void setPrimaryEngine(AsyncEngine * engine); - - /** set the time service. There can be only one time service set at any - * time. The time service is invoked on each loop - */ - void setTimeService(Time::Engine *); - - /** stop the event loop - it will finish the current loop and then return to the - * caller of run(). - */ - void stop(); - - int errcount; - - /// the [main program] loop running now; may be nil - /// for simplicity, we assume there are no concurrent loops - static EventLoop *Running; - -private: - /** setup state variables prior to running */ - void prepareToRun(); - - /** check an individual engine */ - void checkEngine(AsyncEngine * engine, bool const primary); - - /** dispatch calls and events scheduled during checkEngine() */ - bool dispatchCalls(); - - bool last_loop; - typedef std::vector engine_vector; - engine_vector engines; - Time::Engine *timeService; - AsyncEngine * primaryEngine; - int loop_delay; /**< the delay to be given to the primary engine */ - bool error; /**< has an error occurred in this loop */ - bool runOnceResult; /**< the result from runOnce */ -}; - -#endif /* SQUID_SRC_EVENTLOOP_H */ - diff --git a/src/Makefile.am b/src/Makefile.am index e6bb8997182..8446dbb7297 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,7 @@ SUBDIRS = \ time \ debug \ base \ + engines \ anyp \ helper \ dns \ @@ -214,8 +215,6 @@ squid_SOURCES = \ $(WINSVC_SOURCE) \ AccessLogEntry.cc \ AccessLogEntry.h \ - AsyncEngine.cc \ - AsyncEngine.h \ AuthReg.h \ BodyPipe.cc \ BodyPipe.h \ @@ -246,8 +245,6 @@ squid_SOURCES = \ Downloader.h \ ETag.cc \ ETag.h \ - EventLoop.cc \ - EventLoop.h \ ExternalACL.h \ ExternalACLEntry.cc \ ExternalACLEntry.h \ @@ -536,6 +533,7 @@ squid_LDADD = \ $(ADAPTATION_LIBS) \ html/libhtml.la \ $(SNMP_LIBS) \ + engines/libengines.la \ mem/libmem.la \ store/libstore.la \ time/libtime.la \ @@ -998,6 +996,24 @@ tests_testString_LDADD = \ $(XTRA_LIBS) tests_testString_LDFLAGS = $(LIBADD_DL) +# Tests of engines/* + +check_PROGRAMS += tests/testEventLoop +tests_testEventLoop_SOURCES = \ + tests/testEventLoop.cc +nodist_tests_testEventLoop_SOURCES = \ + tests/stub_SBuf.cc \ + tests/stub_debug.cc \ + tests/stub_fatal.cc \ + tests/stub_libtime.cc +tests_testEventLoop_LDADD = \ + engines/libengines.la \ + base/libbase.la \ + $(LIBCPPUNIT_LIBS) \ + $(COMPAT_LIB) \ + $(XTRA_LIBS) +tests_testEventLoop_LDFLAGS = $(LIBADD_DL) + ## Tests of fs/* if ENABLE_FS_ROCK @@ -1015,7 +1031,6 @@ tests_testRock_SOURCES = \ ConfigOption.cc \ ConfigParser.cc \ ETag.cc \ - EventLoop.cc \ FadingCounter.cc \ FileMap.h \ tests/stub_HelperChildConfig.cc \ @@ -1146,6 +1161,7 @@ tests_testRock_LDADD = \ $(SSL_LIBS) \ ipc/libipc.la \ base/libbase.la \ + engines/libengines.la \ mem/libmem.la \ store/libstore.la \ $(ADAPTATION_LIBS) \ @@ -1185,7 +1201,6 @@ tests_testUfs_SOURCES = \ ConfigOption.cc \ ConfigParser.cc \ ETag.cc \ - EventLoop.cc \ FadingCounter.cc \ FileMap.h \ tests/stub_HelperChildConfig.cc \ @@ -1323,6 +1338,7 @@ tests_testUfs_LDADD = \ comm/libcomm.la \ dns/libdns.la \ base/libbase.la \ + engines/libengines.la \ mem/libmem.la \ store/libstore.la \ $(ADAPTATION_LIBS) \ @@ -1359,7 +1375,6 @@ tests_testStore_SOURCES = \ ConfigOption.cc \ ConfigParser.cc \ ETag.cc \ - EventLoop.cc \ FileMap.h \ tests/stub_HelperChildConfig.cc \ HttpBody.cc \ @@ -1486,6 +1501,7 @@ tests_testStore_LDADD= \ fs/libfs.la \ mgr/libmgr.la \ anyp/libanyp.la \ + engines/libengines.la \ mem/libmem.la \ store/libstore.la \ sbuf/libsbuf.la \ @@ -1522,7 +1538,6 @@ tests_testDiskIO_SOURCES = \ ConfigParser.cc \ tests/testDiskIO.cc \ tests/stub_ETag.cc \ - EventLoop.cc \ FadingCounter.cc \ FileMap.h \ tests/stub_HelperChildConfig.cc \ @@ -1666,6 +1681,7 @@ tests_testDiskIO_LDADD = \ ipc/libipc.la \ dns/libdns.la \ base/libbase.la \ + engines/libengines.la \ mem/libmem.la \ sbuf/libsbuf.la \ $(top_builddir)/lib/libmisccontainers.la \ @@ -2080,7 +2096,6 @@ tests_testCacheManager_SOURCES = \ CpuAffinitySet.cc \ CpuAffinitySet.h \ tests/stub_ETag.cc \ - tests/stub_EventLoop.cc \ ExternalACLEntry.cc \ FadingCounter.cc \ FileMap.h \ @@ -2183,6 +2198,7 @@ tests_testCacheManager_SOURCES = \ tests/stub_libauth.cc \ tests/stub_libauth_acls.cc \ tests/stub_libdiskio.cc \ + tests/stub_libengines.cc \ tests/stub_liberror.cc \ tests/stub_libsecurity.cc \ tests/stub_main_cc.cc \ @@ -2375,22 +2391,6 @@ tests_testEvent_LDADD = \ $(XTRA_LIBS) tests_testEvent_LDFLAGS = $(LIBADD_DL) -check_PROGRAMS += tests/testEventLoop -tests_testEventLoop_SOURCES = \ - tests/testEventLoop.cc -nodist_tests_testEventLoop_SOURCES = \ - EventLoop.cc \ - tests/stub_SBuf.cc \ - tests/stub_debug.cc \ - tests/stub_fatal.cc \ - tests/stub_libtime.cc -tests_testEventLoop_LDADD = \ - base/libbase.la \ - $(LIBCPPUNIT_LIBS) \ - $(COMPAT_LIB) \ - $(XTRA_LIBS) -tests_testEventLoop_LDFLAGS = $(LIBADD_DL) - check_PROGRAMS += tests/testIoManip tests_testIoManip_SOURCES = \ tests/testIoManip.cc diff --git a/src/adaptation/ecap/ServiceRep.cc b/src/adaptation/ecap/ServiceRep.cc index 0cc8f65bcc1..ac8e0de54bc 100644 --- a/src/adaptation/ecap/ServiceRep.cc +++ b/src/adaptation/ecap/ServiceRep.cc @@ -13,10 +13,9 @@ #include "adaptation/ecap/Host.h" #include "adaptation/ecap/ServiceRep.h" #include "adaptation/ecap/XactionRep.h" -#include "AsyncEngine.h" #include "base/TextException.h" #include "debug/Stream.h" -#include "EventLoop.h" +#include "engines/EventLoop.h" #if HAVE_LIBECAP_ADAPTER_SERVICE_H #include diff --git a/src/AsyncEngine.h b/src/engines/AsyncEngine.h similarity index 76% rename from src/AsyncEngine.h rename to src/engines/AsyncEngine.h index b3fb05ee038..177beb4ccf4 100644 --- a/src/AsyncEngine.h +++ b/src/engines/AsyncEngine.h @@ -6,35 +6,34 @@ * Please see the COPYING and CONTRIBUTORS files for details. */ -#ifndef SQUID_SRC_ASYNCENGINE_H -#define SQUID_SRC_ASYNCENGINE_H +#ifndef SQUID_SRC_ENGINES_ASYNCENGINE_H +#define SQUID_SRC_ENGINES_ASYNCENGINE_H -/* Abstract interface for async engines which an event loop can utilise. +/** + * Abstract interface for async engines which an event loop can utilise. * * Some implementations will be truly async, others like the event engine * will be pseudo async. */ - class AsyncEngine { - public: /* error codes returned from checkEvents. If the return value is not * negative, then it is the requested delay until the next call. If it is * negative, it is one of the following codes: */ enum CheckError { - /* this engine is completely idle: it has no pending events, and nothing - * registered with it that can create events - */ + /// This engine is completely idle: it has no pending events, and nothing + /// registered with it that can create events. EVENT_IDLE = -1, - /* some error has occurred in this engine */ + /// Some error has occurred in this engine. EVENT_ERROR = -2 }; virtual ~AsyncEngine() {} - /* Check the engine for events. If there are events that have completed, + /** + * Check the engine for events. If there are events that have completed, * the engine should at this point hand them off to their dispatcher. * Engines that operate asynchronously - i.e. the DiskThreads engine - * should hand events off to their dispatcher as they arrive rather than @@ -42,7 +41,7 @@ class AsyncEngine * use this call as the time to perform their checks with the OS for new * events. * - * The return value is the status code of the event checking. If its a + * The return value is the status code of the event checking. If it is 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 @@ -50,10 +49,9 @@ class AsyncEngine * * 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 that's fine though undesirable). + * timeout to do actual checks that is fine, though undesirable). */ virtual int checkEvents(int timeout) = 0; }; -#endif /* SQUID_SRC_ASYNCENGINE_H */ - +#endif /* SQUID_SRC_ENGINES_ASYNCENGINE_H */ diff --git a/src/EventLoop.cc b/src/engines/EventLoop.cc similarity index 70% rename from src/EventLoop.cc rename to src/engines/EventLoop.cc index cdc3e40eb93..c663786cdbb 100644 --- a/src/EventLoop.cc +++ b/src/engines/EventLoop.cc @@ -9,31 +9,18 @@ /* DEBUG: section 01 Main Loop */ #include "squid.h" -#include "AsyncEngine.h" #include "base/AsyncCallQueue.h" #include "debug/Stream.h" -#include "EventLoop.h" +#include "engines/EventLoop.h" #include "fatal.h" #include "time/Engine.h" EventLoop *EventLoop::Running = nullptr; -EventLoop::EventLoop() : errcount(0), last_loop(false), timeService(nullptr), - primaryEngine(nullptr), - loop_delay(EVENT_LOOP_TIMEOUT), - error(false), - runOnceResult(false) -{} - void -EventLoop::checkEngine(AsyncEngine * engine, bool const primary) +EventLoop::checkEngine(AsyncEngine * const engine, const bool primary) { - int requested_delay; - - if (!primary) - requested_delay = engine->checkEvents(0); - else - requested_delay = engine->checkEvents(loop_delay); + auto requested_delay = engine->checkEvents(primary ? loop_delay : 0); if (requested_delay < 0) switch (requested_delay) { @@ -66,12 +53,6 @@ EventLoop::prepareToRun() errcount = 0; } -void -EventLoop::registerEngine(AsyncEngine *engine) -{ - engines.push_back(engine); -} - void EventLoop::run() { @@ -99,10 +80,9 @@ EventLoop::runOnce() do { // generate calls and events - typedef engine_vector::iterator EVI; - for (EVI i = engines.begin(); i != engines.end(); ++i) { - if (*i != waitingEngine) - checkEngine(*i, false); + for (auto engine : engines) { + if (engine != waitingEngine) + checkEngine(engine, false); } // dispatch calls accumulated so far @@ -139,34 +119,21 @@ EventLoop::runOnce() // dispatches calls accumulated during checkEngine() bool -EventLoop::dispatchCalls() +EventLoop::dispatchCalls() const { bool dispatchedSome = AsyncCallQueue::Instance().fire(); return dispatchedSome; } void -EventLoop::setPrimaryEngine(AsyncEngine * engine) +EventLoop::setPrimaryEngine(AsyncEngine * const e) { - for (engine_vector::iterator i = engines.begin(); - i != engines.end(); ++i) - if (*i == engine) { + for (auto engine : engines) { + if (engine == e) { primaryEngine = engine; return; } + } fatal("EventLoop::setPrimaryEngine: No such engine!."); } - -void -EventLoop::setTimeService(Time::Engine *engine) -{ - timeService = engine; -} - -void -EventLoop::stop() -{ - last_loop = true; -} - diff --git a/src/engines/EventLoop.h b/src/engines/EventLoop.h new file mode 100644 index 00000000000..665c89905ff --- /dev/null +++ b/src/engines/EventLoop.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 1996-2026 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + +#ifndef SQUID_SRC_EVENTLOOP_H +#define SQUID_SRC_EVENTLOOP_H + +#include "engines/AsyncEngine.h" +#include "time/forward.h" + +#include + +#if !defined(EVENT_LOOP_TIMEOUT) +/// Maximum timeout for loop checks of the primary engine, in milliseconds. +#define EVENT_LOOP_TIMEOUT 1000 +#endif + +/** An event loop. An event loop is the core inner loop of squid. + * The event loop can be run until exit, or once. After it finishes control + * returns to the caller. If desired it can be run again. + \par + * The event loop cannot be run once it is running until it has finished. + */ +class EventLoop +{ +public: + /** + * Register an engine which will be given the opportunity to perform + * in-main-thread tasks each event loop. + */ + void registerEngine(AsyncEngine *e) { engines.emplace_back(e); } + + /** + * Start this event loop running. The loop will run until it is stopped by + * calling stop(), or when the loop is completely idle - nothing + * dispatched in a loop, and all engines idle. + */ + void run(); + + /** + * This may not complete all events! use with care. + * TODO: signal in runOnce whether or not the loop is over - IDLE vs OK vs + * TIMEOUT? + */ + bool runOnce(); + + /** + * The primary async engine receives the lowest requested timeout gathered + * from the other engines each loop. + * There is a default of EVENT_LOOP_TIMEOUT if all engines are idle, + * or request higher delays. + * + * If no primary has been nominated, the last async engine added is + * implicitly the default. + */ + void setPrimaryEngine(AsyncEngine * const); + + /** + * Nominate a time service to invoke on each loop. + * There can be only one engine acting as time service. + */ + void setTimeService(Time::Engine * const e) { timeService = e; } + + /// Finish the current loop and then return to the caller of run(). + void stop() { last_loop = true; } + +public: + /** + * The [main program] loop running now; may be nil. + * For simplicity, we assume there are no concurrent loops + */ + static EventLoop *Running; + + /// How many errors have occured so far in this iteration of the loop. + int errcount = 0; + +private: + /** setup state variables prior to running */ + void prepareToRun(); + + /** check an individual engine */ + void checkEngine(AsyncEngine * const, const bool primary); + + /** dispatch AsyncCalls scheduled during checkEngine() */ + bool dispatchCalls() const; + +private: + bool last_loop = false; + std::vector engines; + Time::Engine *timeService = nullptr; + AsyncEngine *primaryEngine = nullptr; + + /// the delay to be given to the primary engine + int loop_delay = EVENT_LOOP_TIMEOUT; + + /// has an error occurred in this loop + bool error = false; + + /// the result from runOnce + bool runOnceResult = false; +}; + +#endif /* SQUID_SRC_ENGINES_EVENTLOOP_H */ diff --git a/src/engines/Makefile.am b/src/engines/Makefile.am new file mode 100644 index 00000000000..1e426b4e36e --- /dev/null +++ b/src/engines/Makefile.am @@ -0,0 +1,16 @@ +## Copyright (C) 1996-2026 The Squid Software Foundation and contributors +## +## Squid software is distributed under GPLv2+ license and includes +## contributions from numerous individuals and organizations. +## Please see the COPYING and CONTRIBUTORS files for details. +## + +include $(top_srcdir)/src/Common.am + +noinst_LTLIBRARIES = libengines.la + +libengines_la_SOURCES = \ + AsyncEngine.h \ + EventLoop.cc \ + EventLoop.h \ + forward.h diff --git a/src/AsyncEngine.cc b/src/engines/forward.h similarity index 64% rename from src/AsyncEngine.cc rename to src/engines/forward.h index e3bae3dea99..bc256391085 100644 --- a/src/AsyncEngine.cc +++ b/src/engines/forward.h @@ -6,6 +6,10 @@ * Please see the COPYING and CONTRIBUTORS files for details. */ -#include "squid.h" -#include "AsyncEngine.h" +#ifndef SQUID_SRC_ENGINES_FORWARD_H +#define SQUID_SRC_ENGINES_FORWARD_H +class AsyncEngine; +class EventLoop; + +#endif /* SQUID_SRC_ENGINES_FORWARD_H */ diff --git a/src/event.h b/src/event.h index e1fbeb72a7c..65e36abcc54 100644 --- a/src/event.h +++ b/src/event.h @@ -9,8 +9,8 @@ #ifndef SQUID_SRC_EVENT_H #define SQUID_SRC_EVENT_H -#include "AsyncEngine.h" #include "base/Packable.h" +#include "engines/AsyncEngine.h" #include "mem/forward.h" /* event scheduling facilities - run a callback after a given time period. */ diff --git a/src/main.cc b/src/main.cc index c9ad17f905d..ea44bea7c78 100644 --- a/src/main.cc +++ b/src/main.cc @@ -33,7 +33,7 @@ #include "dns/forward.h" #include "errorpage.h" #include "event.h" -#include "EventLoop.h" +#include "engines/EventLoop.h" #include "ExternalACL.h" #include "fd.h" #include "format/Token.h" diff --git a/src/tests/Stub.am b/src/tests/Stub.am index 47026296055..8611d568f85 100644 --- a/src/tests/Stub.am +++ b/src/tests/Stub.am @@ -16,7 +16,6 @@ STUB_SOURCE = \ tests/stub_CommIO.cc \ tests/stub_DelayId.cc \ tests/stub_ETag.cc \ - tests/stub_EventLoop.cc \ tests/stub_HelperChildConfig.cc \ tests/stub_HttpControlMsg.cc \ tests/stub_HttpHeader.cc \ @@ -64,6 +63,7 @@ STUB_SOURCE = \ tests/stub_libcomm.cc \ tests/stub_libdiskio.cc \ tests/stub_libdns.cc \ + tests/stub_libengines.cc \ tests/stub_liberror.cc \ tests/stub_libeui.cc \ tests/stub_libformat.cc \ diff --git a/src/tests/stub_EventLoop.cc b/src/tests/stub_libengines.cc similarity index 56% rename from src/tests/stub_EventLoop.cc rename to src/tests/stub_libengines.cc index 8567acfbaed..6261d44f058 100644 --- a/src/tests/stub_EventLoop.cc +++ b/src/tests/stub_libengines.cc @@ -7,16 +7,14 @@ */ #include "squid.h" -#include "EventLoop.h" -#define STUB_API "EventLoop.cc" +#define STUB_API "engines/libengines.la" #include "tests/STUB.h" -EventLoop *EventLoop::Running = nullptr; - -EventLoop::EventLoop(): errcount(0), last_loop(false), timeService(nullptr), - primaryEngine(nullptr), loop_delay(0), error(false), runOnceResult(false) - STUB_NOP - - void EventLoop::registerEngine(AsyncEngine *) STUB +#include "engines/AsyncEngine.h" +#include "engines/EventLoop.h" +EventLoop *EventLoop::Running = nullptr; +void EventLoop::run() STUB +bool EventLoop::runOnce() STUB +void EventLoop::setPrimaryEngine(AsyncEngine * const) STUB diff --git a/src/tests/testEventLoop.cc b/src/tests/testEventLoop.cc index 8e3091442fa..1d296f138c6 100644 --- a/src/tests/testEventLoop.cc +++ b/src/tests/testEventLoop.cc @@ -7,9 +7,8 @@ */ #include "squid.h" -#include "AsyncEngine.h" #include "compat/cppunit.h" -#include "EventLoop.h" +#include "engines/EventLoop.h" #include "time/Engine.h" #include "unitTestMain.h" diff --git a/src/tests/testStoreSupport.cc b/src/tests/testStoreSupport.cc index 42b220a6edf..03b3f87b536 100644 --- a/src/tests/testStoreSupport.cc +++ b/src/tests/testStoreSupport.cc @@ -8,7 +8,6 @@ #include "squid.h" #include "event.h" -#include "EventLoop.h" #include "testStoreSupport.h" /* construct a stock loop with event dispatching, a time service that advances diff --git a/src/tests/testStoreSupport.h b/src/tests/testStoreSupport.h index 1808e9df8ad..2bf24e7da30 100644 --- a/src/tests/testStoreSupport.h +++ b/src/tests/testStoreSupport.h @@ -9,7 +9,7 @@ #ifndef SQUID_SRC_TESTS_TESTSTORESUPPORT_H #define SQUID_SRC_TESTS_TESTSTORESUPPORT_H -#include "EventLoop.h" +#include "engines/EventLoop.h" #include "time/Engine.h" /* construct a stock loop with event dispatching, a time service that advances