ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Loop.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\Event\Loop;
4
18class Loop {
19
27 function setTimeout(callable $cb, $timeout) {
28
29 $triggerTime = microtime(true) + ($timeout);
30
31 if (!$this->timers) {
32 // Special case when the timers array was empty.
33 $this->timers[] = [$triggerTime, $cb];
34 return;
35 }
36
37 // We need to insert these values in the timers array, but the timers
38 // array must be in reverse-order of trigger times.
39 //
40 // So here we search the array for the insertion point.
41 $index = count($this->timers) - 1;
42 while (true) {
43 if ($triggerTime < $this->timers[$index][0]) {
44 array_splice(
45 $this->timers,
46 $index + 1,
47 0,
48 [[$triggerTime, $cb]]
49 );
50 break;
51 } elseif ($index === 0) {
52 array_unshift($this->timers, [$triggerTime, $cb]);
53 break;
54 }
55 $index--;
56
57 }
58
59 }
60
71 function setInterval(callable $cb, $timeout) {
72
73 $keepGoing = true;
74 $f = null;
75
76 $f = function() use ($cb, &$f, $timeout, &$keepGoing) {
77 if ($keepGoing) {
78 $cb();
79 $this->setTimeout($f, $timeout);
80 }
81 };
82 $this->setTimeout($f, $timeout);
83
84 // Really the only thing that matters is returning the $keepGoing
85 // boolean value.
86 //
87 // We need to pack it in an array to allow returning by reference.
88 // Because I'm worried people will be confused by using a boolean as a
89 // sort of identifier, I added an extra string.
90 return ['I\'m an implementation detail', &$keepGoing];
91
92 }
93
100 function clearInterval($intervalId) {
101
102 $intervalId[1] = false;
103
104 }
105
112 function nextTick(callable $cb) {
113
114 $this->nextTick[] = $cb;
115
116 }
117
118
132 function addReadStream($stream, callable $cb) {
133
134 $this->readStreams[(int)$stream] = $stream;
135 $this->readCallbacks[(int)$stream] = $cb;
136
137 }
138
152 function addWriteStream($stream, callable $cb) {
153
154 $this->writeStreams[(int)$stream] = $stream;
155 $this->writeCallbacks[(int)$stream] = $cb;
156
157 }
158
166
167 unset(
168 $this->readStreams[(int)$stream],
169 $this->readCallbacks[(int)$stream]
170 );
171
172 }
173
181
182 unset(
183 $this->writeStreams[(int)$stream],
184 $this->writeCallbacks[(int)$stream]
185 );
186
187 }
188
189
198 function run() {
199
200 $this->running = true;
201
202 do {
203
204 $hasEvents = $this->tick(true);
205
206 } while ($this->running && $hasEvents);
207 $this->running = false;
208
209 }
210
226 function tick($block = false) {
227
228 $this->runNextTicks();
229 $nextTimeout = $this->runTimers();
230
231 // Calculating how long runStreams should at most wait.
232 if (!$block) {
233 // Don't wait
234 $streamWait = 0;
235 } elseif ($this->nextTick) {
236 // There's a pending 'nextTick'. Don't wait.
237 $streamWait = 0;
238 } elseif (is_numeric($nextTimeout)) {
239 // Wait until the next Timeout should trigger.
240 $streamWait = $nextTimeout;
241 } else {
242 // Wait indefinitely
243 $streamWait = null;
244 }
245
246 $this->runStreams($streamWait);
247
248 return ($this->readStreams || $this->writeStreams || $this->nextTick || $this->timers);
249
250 }
251
257 function stop() {
258
259 $this->running = false;
260
261 }
262
268 protected function runNextTicks() {
269
271 $this->nextTick = [];
272
273 foreach ($nextTick as $cb) {
274 $cb();
275 }
276
277 }
278
289 protected function runTimers() {
290
291 $now = microtime(true);
292 while (($timer = array_pop($this->timers)) && $timer[0] < $now) {
293 $timer[1]();
294 }
295 // Add the last timer back to the array.
296 if ($timer) {
297 $this->timers[] = $timer;
298 return $timer[0] - microtime(true);
299 }
300
301 }
302
308 protected function runStreams($timeout) {
309
310 if ($this->readStreams || $this->writeStreams) {
311
312 $read = $this->readStreams;
313 $write = $this->writeStreams;
314 $except = null;
315 if (stream_select($read, $write, $except, null, $timeout)) {
316
317 // See PHP Bug https://bugs.php.net/bug.php?id=62452
318 // Fixed in PHP7
319 foreach ($read as $readStream) {
320 $readCb = $this->readCallbacks[(int)$readStream];
321 $readCb();
322 }
323 foreach ($write as $writeStream) {
324 $writeCb = $this->writeCallbacks[(int)$writeStream];
325 $writeCb();
326 }
327
328 }
329
330 } elseif ($this->running && ($this->nextTick || $this->timers)) {
331 usleep($timeout !== null ? $timeout * 1000000 : 200000);
332 }
333
334 }
335
341 protected $running = false;
342
348 protected $timers = [];
349
355 protected $nextTick = [];
356
362 protected $readStreams = [];
363
369 protected $writeStreams = [];
370
376 protected $readCallbacks = [];
377
383 protected $writeCallbacks = [];
384
385
386}
An exception for terminatinating execution or to throw for unit testing.
A simple eventloop implementation.
Definition: Loop.php:18
runNextTicks()
Executes all 'nextTick' callbacks.
Definition: Loop.php:268
setInterval(callable $cb, $timeout)
Executes a function every x seconds.
Definition: Loop.php:71
removeReadStream($stream)
Stop watching a stream for reads.
Definition: Loop.php:165
runStreams($timeout)
Runs all pending stream events.
Definition: Loop.php:308
clearInterval($intervalId)
Stops a running internval.
Definition: Loop.php:100
setTimeout(callable $cb, $timeout)
Executes a function after x seconds.
Definition: Loop.php:27
tick($block=false)
Executes all pending events.
Definition: Loop.php:226
run()
Runs the loop.
Definition: Loop.php:198
runTimers()
Runs all pending timers.
Definition: Loop.php:289
removeWriteStream($stream)
Stop watching a stream for writes.
Definition: Loop.php:180
nextTick(callable $cb)
Runs a function immediately at the next iteration of the loop.
Definition: Loop.php:112
addWriteStream($stream, callable $cb)
Adds a write stream.
Definition: Loop.php:152
stop()
Stops a running eventloop.
Definition: Loop.php:257
addReadStream($stream, callable $cb)
Adds a read stream.
Definition: Loop.php:132
$index
Definition: metadata.php:60
$stream
PHP stream implementation.