]> git.ipfire.org Git - thirdparty/squid.git/blob - src/EventLoop.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / EventLoop.cc
1 /*
2 * Copyright (C) 1996-2021 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 /* DEBUG: section 01 Main Loop */
10
11 #include "squid.h"
12 #include "AsyncEngine.h"
13 #include "base/AsyncCallQueue.h"
14 #include "Debug.h"
15 #include "EventLoop.h"
16 #include "fatal.h"
17 #include "SquidTime.h"
18
19 EventLoop *EventLoop::Running = NULL;
20
21 EventLoop::EventLoop() : errcount(0), last_loop(false), timeService(NULL),
22 primaryEngine(NULL),
23 loop_delay(EVENT_LOOP_TIMEOUT),
24 error(false),
25 runOnceResult(false)
26 {}
27
28 void
29 EventLoop::checkEngine(AsyncEngine * engine, bool const primary)
30 {
31 int requested_delay;
32
33 if (!primary)
34 requested_delay = engine->checkEvents(0);
35 else
36 requested_delay = engine->checkEvents(loop_delay);
37
38 if (requested_delay < 0)
39 switch (requested_delay) {
40
41 case AsyncEngine::EVENT_IDLE:
42 debugs(1, 9, "Engine " << engine << " is idle.");
43 break;
44
45 case AsyncEngine::EVENT_ERROR:
46 runOnceResult = false;
47 error = true;
48 break;
49
50 default:
51 fatal_dump("unknown AsyncEngine result");
52 }
53 else {
54 /* not idle or error */
55 runOnceResult = false;
56
57 if (requested_delay < loop_delay)
58 loop_delay = requested_delay;
59 }
60 }
61
62 void
63 EventLoop::prepareToRun()
64 {
65 last_loop = false;
66 errcount = 0;
67 }
68
69 void
70 EventLoop::registerEngine(AsyncEngine *engine)
71 {
72 engines.push_back(engine);
73 }
74
75 void
76 EventLoop::run()
77 {
78 prepareToRun();
79
80 assert(!Running);
81 Running = this;
82
83 while (!runOnce());
84
85 Running = NULL;
86 }
87
88 bool
89 EventLoop::runOnce()
90 {
91 bool sawActivity = false;
92 runOnceResult = true;
93 error = false;
94 loop_delay = EVENT_LOOP_TIMEOUT;
95
96 AsyncEngine *waitingEngine = primaryEngine;
97 if (!waitingEngine && !engines.empty())
98 waitingEngine = engines.back();
99
100 do {
101 // generate calls and events
102 typedef engine_vector::iterator EVI;
103 for (EVI i = engines.begin(); i != engines.end(); ++i) {
104 if (*i != waitingEngine)
105 checkEngine(*i, false);
106 }
107
108 // dispatch calls accumulated so far
109 sawActivity = dispatchCalls();
110 if (sawActivity)
111 runOnceResult = false;
112 } while (sawActivity);
113
114 if (waitingEngine != NULL)
115 checkEngine(waitingEngine, true);
116
117 if (timeService != NULL)
118 timeService->tick();
119
120 // dispatch calls scheduled by waitingEngine and timeService
121 sawActivity = dispatchCalls();
122 if (sawActivity)
123 runOnceResult = false;
124
125 if (error) {
126 ++errcount;
127 debugs(1, DBG_CRITICAL, "Select loop Error. Retry " << errcount);
128 } else
129 errcount = 0;
130
131 if (errcount == 10)
132 return true;
133
134 if (last_loop)
135 return true;
136
137 return runOnceResult;
138 }
139
140 // dispatches calls accumulated during checkEngine()
141 bool
142 EventLoop::dispatchCalls()
143 {
144 bool dispatchedSome = AsyncCallQueue::Instance().fire();
145 return dispatchedSome;
146 }
147
148 void
149 EventLoop::setPrimaryEngine(AsyncEngine * engine)
150 {
151 for (engine_vector::iterator i = engines.begin();
152 i != engines.end(); ++i)
153 if (*i == engine) {
154 primaryEngine = engine;
155 return;
156 }
157
158 fatal("EventLoop::setPrimaryEngine: No such engine!.");
159 }
160
161 void
162 EventLoop::setTimeService(TimeEngine *engine)
163 {
164 timeService = engine;
165 }
166
167 void
168 EventLoop::stop()
169 {
170 last_loop = true;
171 }
172