]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/base/RunnersRegistry.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / base / RunnersRegistry.cc
index 700dd5653c97455257d2f76ac9ae025a3a33e3c1..ceb72c79b668e219d879583e6177c742913d0632 100644 (file)
-#include "config.h"
+/*
+ * Copyright (C) 1996-2018 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 "squid.h"
 #include "base/RunnersRegistry.h"
-#include <list>
-#include <map>
+#include "base/TextException.h"
+#include <set>
+
+/// a collection of unique runners, in no particular order
+typedef std::set<RegisteredRunner*> Runners;
+/// all known runners
+static Runners *TheRunners = NULL;
+/// used to avoid re-creating deleted TheRunners after shutdown finished.
+static bool RunnersGone = false;
+
+/// creates the registered runners container if needed
+/// \return either registered runners (if they should exist) or nil (otherwise)
+static inline Runners *
+FindRunners()
+{
+    if (!TheRunners && !RunnersGone)
+        TheRunners = new Runners;
+    return TheRunners;
+}
 
-typedef std::list<RegisteredRunner*> Runners;
-typedef std::map<RunnerRegistry, Runners*> Registries;
+static inline void
+GetRidOfRunner(RegisteredRunner *rr)
+{
+    if (!dynamic_cast<IndependentRunner*>(rr))
+        delete rr;
+    // else ignore; IndependentRunner
+}
 
-/// all known registries
-static Registries *TheRegistries = NULL;
+static inline void
+RegisterRunner_(RegisteredRunner *rr)
+{
+    Runners *runners = FindRunners();
+    Must(runners);
+    runners->insert(rr);
+}
 
-/// returns the requested runners list, initializing structures as needed
-static Runners &
-GetRunners(const RunnerRegistry &registryId)
+bool
+RegisterRunner(RegisteredRunner *rr)
 {
-    if (!TheRegistries)
-        TheRegistries = new Registries;
+    Must(!dynamic_cast<IndependentRunner*>(rr));
 
-    if (TheRegistries->find(registryId) == TheRegistries->end())
-        (*TheRegistries)[registryId] = new Runners;
+    if (FindRunners()) {
+        RegisterRunner_(rr);
+        return true;
+    }
 
-    return *(*TheRegistries)[registryId];
+    // past finishShutdown
+    GetRidOfRunner(rr);
+    return false;
 }
 
-int
-RegisterRunner(const RunnerRegistry &registryId, RegisteredRunner *rr)
+void
+RunRegistered(const RegisteredRunner::Method &event)
 {
-    Runners &runners = GetRunners(registryId);
-    runners.push_back(rr);
-    return runners.size();
+    if (Runners *runners = FindRunners()) {
+        // Many things may happen during the loop below. We copy to withstand
+        // runner removal/addition and avoid surprises due to registrations from
+        // parent constructors (with a half-baked "this"!). This copy also
+        // simplifies overall RR logic as it guarantees that registering a
+        // runner during event X loop does not execute runner::X().
+        Runners oldRunners(*runners);
+        for (auto runner: oldRunners) {
+            if (runners->find(runner) != runners->end()) // still registered
+                (runner->*event)();
+        }
+    }
+
+    if (event != &RegisteredRunner::finishShutdown)
+        return;
+
+    // this is the last event; delete registry-dependent runners (and only them)
+    if (Runners *runners = FindRunners()) {
+        RunnersGone = true;
+        TheRunners = nullptr;
+        // from now on, no runners can be registered or unregistered
+        for (auto runner: *runners)
+            GetRidOfRunner(runner); // leaves a dangling pointer in runners
+        delete runners;
+    }
 }
 
-int
-ActivateRegistered(const RunnerRegistry &registryId)
+/* IndependentRunner */
+
+void
+IndependentRunner::unregisterRunner()
 {
-    Runners &runners = GetRunners(registryId);
-    typedef Runners::iterator RRI;
-    for (RRI i = runners.begin(); i != runners.end(); ++i)
-        (*i)->run(registryId);
-    return runners.size();
+    if (Runners *runners = FindRunners())
+        runners->erase(this);
+    // else it is too late, finishShutdown() has been called
 }
 
 void
-DeactivateRegistered(const RunnerRegistry &registryId)
+IndependentRunner::registerRunner()
 {
-    Runners &runners = GetRunners(registryId);
-    while (!runners.empty()) {
-        delete runners.back();
-        runners.pop_back();
-    }
+    if (FindRunners())
+        RegisterRunner_(this);
+    // else do nothing past finishShutdown
 }
 
 bool
@@ -55,3 +112,4 @@ UseThisStatic(const void *)
 {
     return true;
 }
+