]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/RunnersRegistry.cc
d4101b4c4e7ad4ea26b145d186f640b8bdd89d4e
[thirdparty/squid.git] / src / base / RunnersRegistry.cc
1 /*
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "base/RunnersRegistry.h"
11 #include "base/TextException.h"
12 #include <set>
13
14 /// a collection of unique runners, in no particular order
15 typedef std::set<RegisteredRunner*> Runners;
16 /// all known runners
17 static Runners *TheRunners = NULL;
18 /// used to avoid re-creating deleted TheRunners after shutdown finished.
19 static bool RunnersGone = false;
20
21 /// creates the registered runners container if needed
22 /// \return either registered runners (if they should exist) or nil (otherwise)
23 static inline Runners *
24 FindRunners()
25 {
26 if (!TheRunners && !RunnersGone)
27 TheRunners = new Runners;
28 return TheRunners;
29 }
30
31 static inline void
32 GetRidOfRunner(RegisteredRunner *rr)
33 {
34 if (!dynamic_cast<IndependentRunner*>(rr))
35 delete rr;
36 // else ignore; IndependentRunner
37 }
38
39 static inline void
40 RegisterRunner_(RegisteredRunner *rr)
41 {
42 Runners *runners = FindRunners();
43 Must(runners);
44 runners->insert(rr);
45 }
46
47 bool
48 RegisterRunner(RegisteredRunner *rr)
49 {
50 Must(!dynamic_cast<IndependentRunner*>(rr));
51
52 if (FindRunners()) {
53 RegisterRunner_(rr);
54 return true;
55 }
56
57 // past finishShutdown
58 GetRidOfRunner(rr);
59 return false;
60 }
61
62 void
63 RunRegistered(const RegisteredRunner::Method &event)
64 {
65 if (Runners *runners = FindRunners()) {
66 // Many things may happen during the loop below. We copy to withstand
67 // runner removal/addition and avoid surprises due to registrations from
68 // parent constructors (with a half-baked "this"!). This copy also
69 // simplifies overall RR logic as it guarantees that registering a
70 // runner during event X loop does not execute runner::X().
71 Runners oldRunners(*runners);
72 for (auto runner: oldRunners) {
73 if (runners->find(runner) != runners->end()) // still registered
74 (runner->*event)();
75 }
76 }
77
78 if (event != &RegisteredRunner::finishShutdown)
79 return;
80
81 // this is the last event; delete registry-dependent runners (and only them)
82 if (Runners *runners = FindRunners()) {
83 RunnersGone = true;
84 TheRunners = nullptr;
85 // from now on, no runners can be registered or unregistered
86 for (auto runner: *runners)
87 GetRidOfRunner(runner); // leaves a dangling pointer in runners
88 delete runners;
89 }
90 }
91
92 /* IndependentRunner */
93
94 void
95 IndependentRunner::unregisterRunner()
96 {
97 if (Runners *runners = FindRunners())
98 runners->erase(this);
99 // else it is too late, finishShutdown() has been called
100 }
101
102 void
103 IndependentRunner::registerRunner()
104 {
105 if (FindRunners())
106 RegisterRunner_(this);
107 // else do nothing past finishShutdown
108 }
109
110 bool
111 UseThisStatic(const void *)
112 {
113 return true;
114 }
115