Skip to content

Commit c1efdba

Browse files
committed
Changed StreamSelectNextTickLoop to use existing Timers implementation.
1 parent d802ddb commit c1efdba

File tree

4 files changed

+106
-144
lines changed

4 files changed

+106
-144
lines changed

AbstractNextTickLoop.php

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace React\EventLoop;
44

55
use React\EventLoop\Timer\Timer;
6-
use React\EventLoop\Timer\TimerInterface;
76
use SplQueue;
87

98
/**
@@ -20,46 +19,6 @@ public function __construct()
2019
$this->explicitlyStopped = false;
2120
}
2221

23-
/**
24-
* Enqueue a callback to be invoked once after the given interval.
25-
*
26-
* The execution order of timers scheduled to execute at the same time is
27-
* not guaranteed.
28-
*
29-
* @param numeric $interval The number of seconds to wait before execution.
30-
* @param callable $callback The callback to invoke.
31-
*
32-
* @return TimerInterface
33-
*/
34-
public function addTimer($interval, $callback)
35-
{
36-
$timer = new Timer($this, $interval, $callback, false);
37-
38-
$this->scheduleTimer($timer);
39-
40-
return $timer;
41-
}
42-
43-
/**
44-
* Enqueue a callback to be invoked repeatedly after the given interval.
45-
*
46-
* The execution order of timers scheduled to execute at the same time is
47-
* not guaranteed.
48-
*
49-
* @param numeric $interval The number of seconds to wait before execution.
50-
* @param callable $callback The callback to invoke.
51-
*
52-
* @return TimerInterface
53-
*/
54-
public function addPeriodicTimer($interval, $callback)
55-
{
56-
$timer = new Timer($this, $interval, $callback, true);
57-
58-
$this->scheduleTimer($timer);
59-
60-
return $timer;
61-
}
62-
6322
/**
6423
* Schedule a callback to be invoked on the next tick of the event loop.
6524
*
@@ -157,13 +116,6 @@ protected function streamKey($stream)
157116
return (int) $stream;
158117
}
159118

160-
/**
161-
* Schedule a timer for execution.
162-
*
163-
* @param TimerInterface $timer
164-
*/
165-
abstract protected function scheduleTimer(TimerInterface $timer);
166-
167119
/**
168120
* Flush any timer and IO events.
169121
*

ExtEventLoop.php

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Event;
66
use EventBase;
7+
use React\EventLoop\Timer\Timer;
78
use React\EventLoop\Timer\TimerInterface;
89
use SplObjectStorage;
910
use stdClass;
@@ -104,6 +105,46 @@ public function removeStream($stream)
104105
$this->keepAlive[] = $entry->callback;
105106
}
106107

108+
/**
109+
* Enqueue a callback to be invoked once after the given interval.
110+
*
111+
* The execution order of timers scheduled to execute at the same time is
112+
* not guaranteed.
113+
*
114+
* @param numeric $interval The number of seconds to wait before execution.
115+
* @param callable $callback The callback to invoke.
116+
*
117+
* @return TimerInterface
118+
*/
119+
public function addTimer($interval, $callback)
120+
{
121+
$timer = new Timer($this, $interval, $callback, false);
122+
123+
$this->scheduleTimer($timer);
124+
125+
return $timer;
126+
}
127+
128+
/**
129+
* Enqueue a callback to be invoked repeatedly after the given interval.
130+
*
131+
* The execution order of timers scheduled to execute at the same time is
132+
* not guaranteed.
133+
*
134+
* @param numeric $interval The number of seconds to wait before execution.
135+
* @param callable $callback The callback to invoke.
136+
*
137+
* @return TimerInterface
138+
*/
139+
public function addPeriodicTimer($interval, $callback)
140+
{
141+
$timer = new Timer($this, $interval, $callback, true);
142+
143+
$this->scheduleTimer($timer);
144+
145+
return $timer;
146+
}
147+
107148
/**
108149
* Cancel a pending timer.
109150
*
@@ -178,9 +219,9 @@ protected function onTimerTick(TimerInterface $timer)
178219
/**
179220
* Dispatch a stream event.
180221
*
181-
* @param stdClass $entry The entry from $this->streamEvents
182-
* @param stream $stream
183-
* @param integer $flags Bitwise flags indicating event type (Event::READ/Event::WRITE)
222+
* @param stdClass $entry The entry from $this->streamEvents
223+
* @param stream $stream
224+
* @param integer $flags Bitwise flags indicating event type (Event::READ/Event::WRITE)
184225
*/
185226
protected function onStreamEvent($entry, $stream, $flags)
186227
{
@@ -231,8 +272,8 @@ protected function scheduleTimer(TimerInterface $timer)
231272
/**
232273
* Create a new ext-event Event object, or update the existing one.
233274
*
234-
* @param stream $stream
235-
* @param integer $flag Event::READ or Event::WRITE
275+
* @param stream $stream
276+
* @param integer $flag Event::READ or Event::WRITE
236277
* @param callable $listener
237278
*/
238279
protected function addStreamEvent($stream, $flag, $listener)
@@ -268,8 +309,8 @@ protected function addStreamEvent($stream, $flag, $listener)
268309
* Update the ext-event Event object for this stream to stop listening to
269310
* the given event type, or remove it entirely if it's no longer needed.
270311
*
271-
* @param stream $stream
272-
* @param integer $flag Event::READ or Event::WRITE
312+
* @param stream $stream
313+
* @param integer $flag Event::READ or Event::WRITE
273314
*/
274315
protected function removeStreamEvent($stream, $flag)
275316
{

StreamSelectNextTickLoop.php

Lines changed: 49 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
namespace React\EventLoop;
44

5-
use Exception;
65
use React\EventLoop\Timer\Timer;
76
use React\EventLoop\Timer\TimerInterface;
8-
use SplObjectStorage;
9-
use SplPriorityQueue;
10-
use SplQueue;
7+
use React\EventLoop\Timer\Timers;
118

129
/**
1310
* A stream_select() based event-loop with support for nextTick().
@@ -18,13 +15,11 @@ class StreamSelectNextTickLoop extends AbstractNextTickLoop
1815
private $readListeners = [];
1916
private $writeStreams = [];
2017
private $writeListeners = [];
21-
private $timerQueue;
22-
private $timerTimestamps;
18+
private $timers;
2319

2420
public function __construct()
2521
{
26-
$this->timerQueue = new SplPriorityQueue;
27-
$this->timerTimestamps = new SplObjectStorage;
22+
$this->timers = new Timers;
2823

2924
parent::__construct();
3025
}
@@ -102,14 +97,52 @@ public function removeStream($stream)
10297
$this->removeWriteStream($stream);
10398
}
10499

100+
/**
101+
* Enqueue a callback to be invoked once after the given interval.
102+
*
103+
* The execution order of timers scheduled to execute at the same time is
104+
* not guaranteed.
105+
*
106+
* @param numeric $interval The number of seconds to wait before execution.
107+
* @param callable $callback The callback to invoke.
108+
*
109+
* @return TimerInterface
110+
*/
111+
public function addTimer($interval, $callback)
112+
{
113+
$timer = new Timer($this, $interval, $callback, false);
114+
$this->timers->add($timer);
115+
116+
return $timer;
117+
}
118+
119+
/**
120+
* Enqueue a callback to be invoked repeatedly after the given interval.
121+
*
122+
* The execution order of timers scheduled to execute at the same time is
123+
* not guaranteed.
124+
*
125+
* @param numeric $interval The number of seconds to wait before execution.
126+
* @param callable $callback The callback to invoke.
127+
*
128+
* @return TimerInterface
129+
*/
130+
public function addPeriodicTimer($interval, $callback)
131+
{
132+
$timer = new Timer($this, $interval, $callback, true);
133+
$this->timers->add($timer);
134+
135+
return $timer;
136+
}
137+
105138
/**
106139
* Cancel a pending timer.
107140
*
108141
* @param TimerInterface $timer The timer to cancel.
109142
*/
110143
public function cancelTimer(TimerInterface $timer)
111144
{
112-
$this->timerTimestamps->detach($timer);
145+
$this->timers->cancel($timer);
113146
}
114147

115148
/**
@@ -121,7 +154,7 @@ public function cancelTimer(TimerInterface $timer)
121154
*/
122155
public function isTimerActive(TimerInterface $timer)
123156
{
124-
return $this->timerTimestamps->contains($timer);
157+
return $this->timers->contains($timer);
125158
}
126159

127160
/**
@@ -131,7 +164,7 @@ public function isTimerActive(TimerInterface $timer)
131164
*/
132165
protected function flushEvents($blocking)
133166
{
134-
$this->flushTimerQueue();
167+
$this->timers->tick();
135168
$this->waitForStreamActivity($blocking);
136169
}
137170

@@ -142,7 +175,7 @@ protected function flushEvents($blocking)
142175
*/
143176
protected function isEmpty()
144177
{
145-
return 0 === count($this->timerTimestamps)
178+
return $this->timers->isEmpty()
146179
&& 0 === count($this->readStreams)
147180
&& 0 === count($this->writeStreams);
148181
}
@@ -175,8 +208,8 @@ protected function toMicroSeconds($seconds)
175208
* Emulate a stream_select() implementation that does not break when passed
176209
* empty stream arrays.
177210
*
178-
* @param array &$read An array of read streams to select upon.
179-
* @param array &$write An array of write streams to select upon.
211+
* @param array &$read An array of read streams to select upon.
212+
* @param array &$write An array of write streams to select upon.
180213
* @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
181214
*/
182215
protected function streamSelect(array &$read, array &$write, $timeout)
@@ -198,85 +231,17 @@ protected function streamSelect(array &$read, array &$write, $timeout)
198231
return 0;
199232
}
200233

201-
/**
202-
* Schedule a timer for execution.
203-
*
204-
* @param TimerInterface $timer
205-
*/
206-
protected function scheduleTimer(TimerInterface $timer)
207-
{
208-
$executeAt = $this->now() + $this->toMicroSeconds(
209-
$timer->getInterval()
210-
);
211-
212-
$this->timerQueue->insert($timer, -$executeAt);
213-
$this->timerTimestamps->attach($timer, $executeAt);
214-
}
215-
216-
/**
217-
* Get the timer next schedule to tick, if any.
218-
*
219-
* @return TimerInterface|null
220-
*/
221-
protected function nextActiveTimer()
222-
{
223-
while ($this->timerQueue->count()) {
224-
$timer = $this->timerQueue->top();
225-
226-
if ($this->isTimerActive($timer)) {
227-
return $timer;
228-
} else {
229-
$this->timerQueue->extract();
230-
}
231-
}
232-
233-
return null;
234-
}
235-
236-
/**
237-
* Push callbacks for timers that are ready into the next-tick queue.
238-
*/
239-
protected function flushTimerQueue()
240-
{
241-
$now = $this->now();
242-
243-
while ($timer = $this->nextActiveTimer()) {
244-
245-
$executeAt = $this->timerTimestamps[$timer];
246-
247-
// The next time is in the future, exit the loop ...
248-
if ($executeAt > $now) {
249-
break;
250-
}
251-
252-
$this->timerQueue->extract();
253-
254-
call_user_func($timer->getCallback(), $timer);
255-
256-
// Timer cancelled itself ...
257-
if (!$this->isTimerActive($timer)) {
258-
return;
259-
// Reschedule periodic timers ...
260-
} elseif ($timer->isPeriodic()) {
261-
$this->scheduleTimer($timer);
262-
// Cancel one-shot timers ...
263-
} else {
264-
$this->cancelTimer($timer);
265-
}
266-
}
267-
}
268-
269234
protected function waitForStreamActivity($blocking)
270235
{
271236
// The $blocking flag takes precedence ...
272237
if (!$blocking) {
273238
$timeout = 0;
274239

275240
// There is a pending timer, only block until it is due ...
276-
} elseif ($timer = $this->nextActiveTimer()) {
241+
} elseif ($scheduledAt = $this->timers->getFirst()) {
277242
$timeout = max(
278243
0,
279-
$this->timerTimestamps[$timer] - $this->now()
244+
$scheduledAt - $this->timers->getTime()
280245
);
281246

282247
// The only possible event is stream activity, so wait forever ...

Timer/Timers.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,17 @@ public function cancel(TimerInterface $timer)
5656

5757
public function getFirst()
5858
{
59-
if ($this->scheduler->isEmpty()) {
60-
return null;
61-
}
59+
while ($this->scheduler->count()) {
60+
$timer = $this->scheduler->top();
61+
62+
if ($this->timers->contains($timer)) {
63+
return $this->timers[$timer];
64+
}
6265

63-
$scheduledAt = $this->timers[$this->scheduler->top()];
66+
$this->scheduler->extract();
67+
}
6468

65-
return $scheduledAt;
69+
return null;
6670
}
6771

6872
public function isEmpty()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy