Skip to content

Commit eaaed7c

Browse files
authored
Merge pull request #103 from clue-labs/ticks
Tick callback receives no arguments, fix cyclic dependency
2 parents 9483983 + 4827e00 commit eaaed7c

11 files changed

+83
-27
lines changed

README.md

+25-4
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,33 @@ schedule a callback to be invoked on a future tick of the event loop.
251251
This works very much similar to timers with an interval of zero seconds,
252252
but does not require the overhead of scheduling a timer queue.
253253

254-
Unlike timers, callbacks are guaranteed to be executed in the order they
255-
are enqueued.
254+
The tick callback function MUST be able to accept zero parameters.
255+
256+
The tick callback function MUST NOT throw an `Exception`.
257+
The return value of the tick callback function will be ignored and has
258+
no effect, so for performance reasons you're recommended to not return
259+
any excessive data structures.
260+
261+
If you want to access any variables within your callback function, you
262+
can bind arbitrary data to a callback closure like this:
263+
264+
```php
265+
function hello(LoopInterface $loop, $name)
266+
{
267+
$loop->futureTick(function () use ($name) {
268+
echo "hello $name\n";
269+
});
270+
}
271+
272+
hello('Tester');
273+
```
274+
275+
Unlike timers, tick callbacks are guaranteed to be executed in the order
276+
they are enqueued.
256277
Also, once a callback is enqueued, there's no way to cancel this operation.
257278

258-
This is often used to break down bigger tasks into smaller steps (a form of
259-
cooperative multitasking).
279+
This is often used to break down bigger tasks into smaller steps (a form
280+
of cooperative multitasking).
260281

261282
```php
262283
$loop->futureTick(function () {

examples/91-benchmark-ticks.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
$n = isset($argv[1]) ? (int)$argv[1] : 1000 * 100;
1010

1111
for ($i = 0; $i < $n; ++$i) {
12-
$loop->nextTick(function () { });
12+
$loop->futureTick(function () { });
1313
}
1414

1515
$loop->run();

examples/93-benchmark-ticks-delay.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
if ($ticks > 0) {
1212
--$ticks;
1313
//$loop->addTimer(0, $tick);
14-
$loop->nextTick($tick);
14+
$loop->futureTick($tick);
1515
} else {
1616
echo 'done';
1717
}

examples/94-benchmark-timers-delay.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
$tick = function () use (&$tick, &$ticks, $loop) {
1111
if ($ticks > 0) {
1212
--$ticks;
13-
//$loop->nextTick($tick);
13+
//$loop->futureTick($tick);
1414
$loop->addTimer(0, $tick);
1515
} else {
1616
echo 'done';

src/ExtEventLoop.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ExtEventLoop implements LoopInterface
2929
public function __construct(EventBaseConfig $config = null)
3030
{
3131
$this->eventBase = new EventBase($config);
32-
$this->futureTickQueue = new FutureTickQueue($this);
32+
$this->futureTickQueue = new FutureTickQueue();
3333
$this->timerEvents = new SplObjectStorage();
3434

3535
$this->createTimerCallback();

src/LibEvLoop.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class LibEvLoop implements LoopInterface
2626
public function __construct()
2727
{
2828
$this->loop = new EventLoop();
29-
$this->futureTickQueue = new FutureTickQueue($this);
29+
$this->futureTickQueue = new FutureTickQueue();
3030
$this->timerEvents = new SplObjectStorage();
3131
}
3232

src/LibEventLoop.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class LibEventLoop implements LoopInterface
3030
public function __construct()
3131
{
3232
$this->eventBase = event_base_new();
33-
$this->futureTickQueue = new FutureTickQueue($this);
33+
$this->futureTickQueue = new FutureTickQueue();
3434
$this->timerEvents = new SplObjectStorage();
3535

3636
$this->createTimerCallback();

src/LoopInterface.php

+39-4
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,49 @@ public function isTimerActive(TimerInterface $timer);
193193
* This works very much similar to timers with an interval of zero seconds,
194194
* but does not require the overhead of scheduling a timer queue.
195195
*
196-
* Unlike timers, callbacks are guaranteed to be executed in the order they
197-
* are enqueued.
196+
* The tick callback function MUST be able to accept zero parameters.
197+
*
198+
* The tick callback function MUST NOT throw an `Exception`.
199+
* The return value of the tick callback function will be ignored and has
200+
* no effect, so for performance reasons you're recommended to not return
201+
* any excessive data structures.
202+
*
203+
* If you want to access any variables within your callback function, you
204+
* can bind arbitrary data to a callback closure like this:
205+
*
206+
* ```php
207+
* function hello(LoopInterface $loop, $name)
208+
* {
209+
* $loop->futureTick(function () use ($name) {
210+
* echo "hello $name\n";
211+
* });
212+
* }
213+
*
214+
* hello('Tester');
215+
* ```
216+
*
217+
* Unlike timers, tick callbacks are guaranteed to be executed in the order
218+
* they are enqueued.
198219
* Also, once a callback is enqueued, there's no way to cancel this operation.
199220
*
200-
* This is often used to break down bigger tasks into smaller steps (a form of
201-
* cooperative multitasking).
221+
* This is often used to break down bigger tasks into smaller steps (a form
222+
* of cooperative multitasking).
223+
*
224+
* ```php
225+
* $loop->futureTick(function () {
226+
* echo 'b';
227+
* });
228+
* $loop->futureTick(function () {
229+
* echo 'c';
230+
* });
231+
* echo 'a';
232+
* ```
233+
*
234+
* See also [example #3](examples).
202235
*
203236
* @param callable $listener The callback to invoke.
237+
*
238+
* @return void
204239
*/
205240
public function futureTick(callable $listener);
206241

src/StreamSelectLoop.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class StreamSelectLoop implements LoopInterface
2424

2525
public function __construct()
2626
{
27-
$this->futureTickQueue = new FutureTickQueue($this);
27+
$this->futureTickQueue = new FutureTickQueue();
2828
$this->timers = new Timers();
2929
}
3030

src/Tick/FutureTickQueue.php

+11-10
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@
22

33
namespace React\EventLoop\Tick;
44

5-
use React\EventLoop\LoopInterface;
65
use SplQueue;
76

8-
class FutureTickQueue
7+
/**
8+
* A tick queue implementation that can hold multiple callback functions
9+
*
10+
* This class should only be used internally, see LoopInterface instead.
11+
*
12+
* @see LoopInterface
13+
* @internal
14+
*/
15+
final class FutureTickQueue
916
{
10-
private $eventLoop;
1117
private $queue;
1218

13-
/**
14-
* @param LoopInterface $eventLoop The event loop passed as the first parameter to callbacks.
15-
*/
16-
public function __construct(LoopInterface $eventLoop)
19+
public function __construct()
1720
{
18-
$this->eventLoop = $eventLoop;
1921
$this->queue = new SplQueue();
2022
}
2123

@@ -41,8 +43,7 @@ public function tick()
4143

4244
while ($count--) {
4345
call_user_func(
44-
$this->queue->dequeue(),
45-
$this->eventLoop
46+
$this->queue->dequeue()
4647
);
4748
}
4849
}

tests/AbstractLoopTest.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,7 @@ public function testFutureTick()
296296
{
297297
$called = false;
298298

299-
$callback = function ($loop) use (&$called) {
300-
$this->assertSame($this->loop, $loop);
299+
$callback = function () use (&$called) {
301300
$called = true;
302301
};
303302

0 commit comments

Comments
 (0)