/* * Copyright (C) 1996-2024 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_BASE_RUNNERSREGISTRY_H #define SQUID_SRC_BASE_RUNNERSREGISTRY_H /** * This API allows virtually any module to register its interest in receiving * notification about initial configuration availability, configuration changes * and other critical events in Squid lifetime without exposing the notifier * to the details of the module. * * For example, main.cc may activate registered I/O modules after parsing * squid.conf and deactivate them before exiting, all without knowing what * those I/O modules really are. * * A module in this context is code providing a functionality or service to the * rest of Squid, such as src/DiskIO/Blocking, src/fs/ufs, or Cache Manager. To * receive notifications, a module must declare a RegisteredRunner child class * and implement the methods corresponding to the events the module is * interested in. * * The order of events is documented in this header (where applicable), but * the order in which runners are notified about a given event is undefined. * If a specific notification order is required, split the event into two or * more related event(s), documenting their relative order here. * */ /// a runnable registrant API /// kids must override [only] the methods they are interested in class RegisteredRunner { public: /* Related methods below are declared in their calling order */ /* Configuration events */ /// Called right before parsing squid.conf. /// Meant for initializing/preparing configuration parsing facilities. virtual void bootstrapConfig() {} /// Called after parsing squid.conf. /// Meant for setting configuration options that depend on other /// configuration options and were not explicitly configured. virtual void finalizeConfig() {} /// Called after finalizeConfig(). /// Meant for announcing memory reservations before memory is allocated. virtual void claimMemoryNeeds() {} /// Called after claimMemoryNeeds(). /// Meant for activating modules and features using a finalized /// configuration with known memory requirements. virtual void useConfig() {} /* Reconfiguration events */ /// Called after receiving a reconfigure request and before parsing squid.conf. /// Meant for modules that need to prepare for their configuration being changed /// [outside their control]. The changes end with the syncConfig() event. virtual void startReconfigure() {} /// Called after parsing squid.conf during reconfiguration. /// Meant for adjusting the module state based on configuration changes. virtual void syncConfig() {} /* Shutdown events */ /// Called after receiving a shutdown request and before stopping the main /// loop. At least one main loop iteration is guaranteed after this call. /// Meant for cleanup and state saving that may require other modules. virtual void startShutdown() {} /// Called after shutdown_lifetime grace period ends and before stopping /// the main loop. At least one main loop iteration is guaranteed after /// this call. /// Meant for cleanup and state saving that may require other modules. virtual void endingShutdown() {} /// Called after stopping the main loop and before releasing memory. /// Meant for quick/basic cleanup that does not require any other modules. virtual ~RegisteredRunner() {} /// Meant for cleanup of services needed by the already destroyed objects. virtual void finishShutdown() {} /// a pointer to one of the above notification methods typedef void (RegisteredRunner::*Method)(); }; /// registers a given runner with the given registry and returns true on success bool RegisterRunner(RegisteredRunner *rr); /// Calls a given method of all runners. /// All runners are destroyed after the finishShutdown() call. void RunRegistered(const RegisteredRunner::Method &m); /// A RegisteredRunner with lifetime determined by forces outside the Registry. class IndependentRunner: public RegisteredRunner { public: ~IndependentRunner() override { unregisterRunner(); } protected: void registerRunner(); void unregisterRunner(); ///< unregisters self; safe to call multiple times }; /// convenience macro to describe/debug the caller and the method being called #define RunRegisteredHere(m) \ debugs(1, 2, "running " # m); \ RunRegistered(&m) /// helps DefineRunnerRegistrator() and CallRunnerRegistrator() (and their /// namespace-sensitive variants) to use the same registration function name #define NameRunnerRegistrator_(Namespace, ClassName) \ Register ## ClassName ## In ## Namespace() /// helper macro that implements DefineRunnerRegistrator() and /// DefineRunnerRegistratorIn() using supplied constructor expression #define DefineRunnerRegistrator_(Namespace, ClassName, Constructor) \ void NameRunnerRegistrator_(Namespace, ClassName); \ void NameRunnerRegistrator_(Namespace, ClassName) { \ const auto registered = RegisterRunner(new Constructor); \ assert(registered); \ } /// Define registration code for the given RegisteredRunner-derived class known /// as ClassName in Namespace. A matching CallRunnerRegistratorIn() call should /// run this code before any possible use of the being-registered module. /// \sa DefineRunnerRegistrator() for classes declared in the global namespace. #define DefineRunnerRegistratorIn(Namespace, ClassName) \ DefineRunnerRegistrator_(Namespace, ClassName, Namespace::ClassName) /// Define registration code for the given RegisteredRunner-derived class known /// as ClassName (in global namespace). A matching CallRunnerRegistrator() call /// should run this code before any possible use of the being-registered module. /// \sa DefineRunnerRegistratorIn() for classes declared in named namespaces. #define DefineRunnerRegistrator(ClassName) \ DefineRunnerRegistrator_(Global, ClassName, ClassName) /// Register one RegisteredRunner kid, known as ClassName in Namespace. /// \sa CallRunnerRegistrator() for classes declared in the global namespace. #define CallRunnerRegistratorIn(Namespace, ClassName) \ do { \ void NameRunnerRegistrator_(Namespace, ClassName); \ NameRunnerRegistrator_(Namespace, ClassName); \ } while (false) /// Register one RegisteredRunner kid, known as ClassName (in the global namespace). /// \sa CallRunnerRegistratorIn() for classes declared in named namespaces. #define CallRunnerRegistrator(ClassName) \ CallRunnerRegistratorIn(Global, ClassName) #endif /* SQUID_SRC_BASE_RUNNERSREGISTRY_H */