Skip to content

[RFC] Singularity #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"autoload": {
"psr-4": {
"React\\EventLoop\\": "src"
}
},
"files": ["src/functions.php"]
},
"extra": {
"branch-alias": {
Expand Down
4 changes: 2 additions & 2 deletions src/ExtEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public function removeStream($stream)
*/
public function addTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, false);
$timer = new Timer($interval, $callback, false);

$this->scheduleTimer($timer);

Expand All @@ -126,7 +126,7 @@ public function addTimer($interval, callable $callback)
*/
public function addPeriodicTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, true);
$timer = new Timer($interval, $callback, true);

$this->scheduleTimer($timer);

Expand Down
21 changes: 0 additions & 21 deletions src/Factory.php

This file was deleted.

4 changes: 2 additions & 2 deletions src/LibEvLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function removeStream($stream)
*/
public function addTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, false);
$timer = new Timer($interval, $callback, false);

$callback = function () use ($timer) {
call_user_func($timer->getCallback(), $timer);
Expand All @@ -125,7 +125,7 @@ public function addTimer($interval, callable $callback)
*/
public function addPeriodicTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, true);
$timer = new Timer($interval, $callback, true);

$callback = function () use ($timer) {
call_user_func($timer->getCallback(), $timer);
Expand Down
4 changes: 2 additions & 2 deletions src/LibEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function removeStream($stream)
*/
public function addTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, false);
$timer = new Timer($interval, $callback, false);

$this->scheduleTimer($timer);

Expand All @@ -131,7 +131,7 @@ public function addTimer($interval, callable $callback)
*/
public function addPeriodicTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, true);
$timer = new Timer($interval, $callback, true);

$this->scheduleTimer($timer);

Expand Down
8 changes: 8 additions & 0 deletions src/State.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace React\EventLoop;

class State
{
static public $loop;
}
4 changes: 2 additions & 2 deletions src/StreamSelectLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public function removeStream($stream)
*/
public function addTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, false);
$timer = new Timer($interval, $callback, false);

$this->timers->add($timer);

Expand All @@ -109,7 +109,7 @@ public function addTimer($interval, callable $callback)
*/
public function addPeriodicTimer($interval, callable $callback)
{
$timer = new Timer($this, $interval, $callback, true);
$timer = new Timer($interval, $callback, true);

$this->timers->add($timer);

Expand Down
13 changes: 2 additions & 11 deletions src/Tick/FutureTickQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@

namespace React\EventLoop\Tick;

use React\EventLoop\LoopInterface;
use SplQueue;

class FutureTickQueue
{
private $eventLoop;
private $queue;

/**
* @param LoopInterface $eventLoop The event loop passed as the first parameter to callbacks.
*/
public function __construct(LoopInterface $eventLoop)
public function __construct()
{
$this->eventLoop = $eventLoop;
$this->queue = new SplQueue();
}

Expand All @@ -40,10 +34,7 @@ public function tick()
$count = $this->queue->count();

while ($count--) {
call_user_func(
$this->queue->dequeue(),
$this->eventLoop
);
call_user_func($this->queue->dequeue());
}
}

Expand Down
13 changes: 2 additions & 11 deletions src/Tick/NextTickQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@

namespace React\EventLoop\Tick;

use React\EventLoop\LoopInterface;
use SplQueue;

class NextTickQueue
{
private $eventLoop;
private $queue;

/**
* @param LoopInterface $eventLoop The event loop passed as the first parameter to callbacks.
*/
public function __construct(LoopInterface $eventLoop)
public function __construct()
{
$this->eventLoop = $eventLoop;
$this->queue = new SplQueue();
}

Expand All @@ -38,10 +32,7 @@ public function add(callable $listener)
public function tick()
{
while (!$this->queue->isEmpty()) {
call_user_func(
$this->queue->dequeue(),
$this->eventLoop
);
call_user_func($this->queue->dequeue());
}
}

Expand Down
15 changes: 4 additions & 11 deletions src/Timer/Timer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,29 @@

namespace React\EventLoop\Timer;

use React\EventLoop\LoopInterface;
use React\EventLoop as l;

class Timer implements TimerInterface
{
const MIN_INTERVAL = 0.000001;

protected $loop;
protected $interval;
protected $callback;
protected $periodic;
protected $data;

public function __construct(LoopInterface $loop, $interval, callable $callback, $periodic = false, $data = null)
public function __construct($interval, callable $callback, $periodic = false, $data = null)
{
if ($interval < self::MIN_INTERVAL) {
$interval = self::MIN_INTERVAL;
}

$this->loop = $loop;
$this->interval = (float) $interval;
$this->callback = $callback;
$this->periodic = (bool) $periodic;
$this->data = null;
}

public function getLoop()
{
return $this->loop;
}

public function getInterval()
{
return $this->interval;
Expand Down Expand Up @@ -59,11 +52,11 @@ public function isPeriodic()

public function isActive()
{
return $this->loop->isTimerActive($this);
return l\loop()->isTimerActive($this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO it makes sense to no longer expose the loop as part of the timer interface (i.e. drop the getLoop() method).

Though arguably, I'm also pro exposing the one loop via global state.

However, I consider this very change a design flaw. Unless we move this logic to the timer itself, it actually does have a dependency on the loop. Accessing global state here means we're using a leaky abstraction and hiding the dependencies this particular class has. Also, this does make testing harder (no built-in mechanism to mock the loop).

}

public function cancel()
{
$this->loop->cancelTimer($this);
l\loop()->cancelTimer($this);
}
}
1 change: 0 additions & 1 deletion src/Timer/TimerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

interface TimerInterface
{
public function getLoop();
public function getInterval();
public function getCallback();
public function setData($data);
Expand Down
30 changes: 30 additions & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace React\EventLoop;

function create()
{
// @codeCoverageIgnoreStart
if (function_exists('event_base_new')) {
return new LibEventLoop();
} else if (class_exists('libev\EventLoop', false)) {
return new LibEvLoop;
} else if (class_exists('EventBase', false)) {
return new ExtEventLoop;
}

return new StreamSelectLoop();
// @codeCoverageIgnoreEnd
}

function loop() {
if (!State::$loop) {
State::$loop = create();
}
return State::$loop;
}

function register(LoopInterface $loop)
{
State::$loop = $loop;
}
9 changes: 5 additions & 4 deletions tests/AbstractLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

namespace React\Tests\EventLoop;

use React\EventLoop as l;

abstract class AbstractLoopTest extends TestCase
{
protected $loop;

public function setUp()
{
$this->loop = $this->createLoop();
l\register($this->loop);
}

abstract public function createLoop();
Expand Down Expand Up @@ -235,8 +238,7 @@ public function testNextTick()
{
$called = false;

$callback = function ($loop) use (&$called) {
$this->assertSame($this->loop, $loop);
$callback = function () use (&$called) {
$called = true;
};

Expand Down Expand Up @@ -359,8 +361,7 @@ public function testFutureTick()
{
$called = false;

$callback = function ($loop) use (&$called) {
$this->assertSame($this->loop, $loop);
$callback = function () use (&$called) {
$called = true;
};

Expand Down
7 changes: 7 additions & 0 deletions tests/Timer/AbstractTimerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use React\Tests\EventLoop\TestCase;
use React\EventLoop\Timer\Timers;
use React\EventLoop as l;

abstract class AbstractTimerTest extends TestCase
{
Expand All @@ -14,6 +15,7 @@ public function testAddTimer()
// usleep is intentionally high

$loop = $this->createLoop();
l\register($loop);

$loop->addTimer(0.001, $this->expectCallableOnce());
usleep(1000);
Expand All @@ -23,6 +25,7 @@ public function testAddTimer()
public function testAddPeriodicTimer()
{
$loop = $this->createLoop();
l\register($loop);

$loop->addPeriodicTimer(0.001, $this->expectCallableExactly(3));
usleep(1000);
Expand All @@ -36,6 +39,7 @@ public function testAddPeriodicTimer()
public function testAddPeriodicTimerWithCancel()
{
$loop = $this->createLoop();
l\register($loop);

$timer = $loop->addPeriodicTimer(0.001, $this->expectCallableExactly(2));

Expand All @@ -55,6 +59,7 @@ public function testAddPeriodicTimerCancelsItself()
$i = 0;

$loop = $this->createLoop();
l\register($loop);

$loop->addPeriodicTimer(0.001, function ($timer) use (&$i) {
$i++;
Expand All @@ -77,6 +82,7 @@ public function testAddPeriodicTimerCancelsItself()
public function testIsTimerActive()
{
$loop = $this->createLoop();
l\register($loop);

$timer = $loop->addPeriodicTimer(0.001, function () {});

Expand All @@ -90,6 +96,7 @@ public function testIsTimerActive()
public function testMinimumIntervalOneMicrosecond()
{
$loop = $this->createLoop();
l\register($loop);

$timer = $loop->addTimer(0, function () {});

Expand Down