Skip to content

Commit 564590a

Browse files
committed
Initial commit
0 parents  commit 564590a

8 files changed

+255
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor
2+
composer.lock

composer.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "voryx/pool-poretni-cnysa-tcaer",
3+
"license": "MIT",
4+
"authors": [
5+
{
6+
"name": "Matt Bonneau",
7+
"email": "[email protected]"
8+
},
9+
{
10+
"name": "David Dan",
11+
"email": "[email protected]"
12+
}
13+
],
14+
"require": {
15+
"php": "^7.0",
16+
"async-interop/event-loop": "^0.3",
17+
"react/event-loop": "^0.4.2"
18+
},
19+
"require-dev": {
20+
"amphp/loop": "dev-master",
21+
"phpunit/phpunit": "^5.0",
22+
"wyrihaximus/react-async-interop-loop": "dev-master"
23+
},
24+
"autoload": {
25+
"psr-4": {
26+
"Voryx\\React\\EventLoop\\": "src/"
27+
}
28+
}
29+
}

phpunit.xml.dist

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="tests/bootstrap.php" colors="true">
3+
<testsuites>
4+
<testsuite name="Test Suite">
5+
<directory>tests/</directory>
6+
</testsuite>
7+
</testsuites>
8+
<filter>
9+
<whitelist>
10+
<directory suffix=".php">src/</directory>
11+
</whitelist>
12+
</filter>
13+
</phpunit>

src/ReactAsyncInteropLoop.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
namespace Voryx\React\EventLoop;
4+
5+
use Interop\Async\Loop;
6+
use React\EventLoop\LoopInterface;
7+
use React\EventLoop\Timer\TimerInterface;
8+
9+
class ReactAsyncInteropLoop implements LoopInterface
10+
{
11+
private $readStreams = [];
12+
private $writeStreams = [];
13+
14+
public function addReadStream($stream, callable $listener)
15+
{
16+
$key = (int)$stream;
17+
if (isset($this->readStreams[$key])) {
18+
throw new \Exception('key set twice');
19+
}
20+
$this->readStreams[$key] = Loop::get()->onReadable($stream, function () use ($listener, $stream) {
21+
$listener($stream);
22+
});
23+
}
24+
25+
public function addWriteStream($stream, callable $listener)
26+
{
27+
$key = (int)$stream;
28+
29+
if (isset($this->writeStreams[$key])) {
30+
throw new \Exception('key set twice');
31+
}
32+
33+
$this->writeStreams[$key] = Loop::get()->onWritable($stream, function () use ($listener, $stream) {
34+
$listener($stream);
35+
});
36+
}
37+
38+
public function removeReadStream($stream)
39+
{
40+
$key = (int)$stream;
41+
if (isset($this->readStreams[$key])) {
42+
Loop::get()->cancel($this->readStreams[$key]);
43+
unset($this->readStreams[$key]);
44+
}
45+
}
46+
47+
public function removeWriteStream($stream)
48+
{
49+
$key = (int)$stream;
50+
if (isset($this->writeStreams[$key])) {
51+
Loop::get()->cancel($this->writeStreams[$key]);
52+
unset($this->writeStreams[$key]);
53+
}
54+
}
55+
56+
public function removeStream($stream)
57+
{
58+
$this->removeReadStream($stream);
59+
$this->removeWriteStream($stream);
60+
}
61+
62+
private function addWrappedTimer($interval, callable $callback, $isPeriodic = false)
63+
{
64+
$wrappedCallback = function () use (&$timer, $callback) {
65+
$callback($timer);
66+
};
67+
$millis = $interval * 1000;
68+
if ($isPeriodic) {
69+
$timerKey = Loop::get()->repeat($millis, $wrappedCallback);
70+
} else {
71+
$timerKey = Loop::get()->delay($millis, $wrappedCallback);
72+
}
73+
$timer = new ReactAsyncInteropTimer(
74+
$timerKey,
75+
$interval,
76+
$callback,
77+
$this,
78+
false
79+
);
80+
return $timer;
81+
}
82+
83+
public function addTimer($interval, callable $callback)
84+
{
85+
return $this->addWrappedTimer($interval, $callback);
86+
}
87+
88+
public function addPeriodicTimer($interval, callable $callback)
89+
{
90+
return $this->addWrappedTimer($interval, $callback, true);
91+
}
92+
93+
public function cancelTimer(TimerInterface $timer)
94+
{
95+
$timer->cancel();
96+
}
97+
98+
public function isTimerActive(TimerInterface $timer)
99+
{
100+
return $timer->isActive();
101+
}
102+
103+
public function nextTick(callable $listener)
104+
{
105+
Loop::get()->defer(function () use ($listener) {
106+
$listener($this);
107+
});
108+
}
109+
110+
public function futureTick(callable $listener)
111+
{
112+
$this->nextTick($listener);
113+
}
114+
115+
public function tick()
116+
{
117+
$loop = Loop::get();
118+
119+
$loop->defer(function () use ($loop) {
120+
$loop->stop();
121+
});
122+
123+
$loop->run();
124+
}
125+
126+
public function run()
127+
{
128+
Loop::get()->run();
129+
}
130+
131+
public function stop()
132+
{
133+
Loop::get()->stop();
134+
}
135+
}

src/ReactAsyncInteropTimer.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Voryx\React\EventLoop;
4+
5+
use Interop\Async\Loop;
6+
use React\EventLoop\LoopInterface;
7+
use React\EventLoop\Timer\Timer;
8+
9+
class ReactAsyncInteropTimer extends Timer
10+
{
11+
private $timerKey;
12+
13+
public function __construct($timerKey, $interval, callable $callback, LoopInterface $loop, $isPeriodic = false, $data = null)
14+
{
15+
$this->timerKey = $timerKey;
16+
17+
parent::__construct($loop, $interval, $callback, $isPeriodic, $data);
18+
}
19+
20+
public function cancel()
21+
{
22+
Loop::get()->cancel($this->timerKey);
23+
}
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Voryx\Tests\React\EventLoop;
4+
5+
use Interop\Async\Loop;
6+
use React\EventLoop\StreamSelectLoop;
7+
use React\Tests\EventLoop\AbstractLoopTest;
8+
use Voryx\React\EventLoop\ReactAsyncInteropLoop;
9+
use WyriHaximus\React\AsyncInteropLoop\ReactDriverFactory;
10+
11+
class ReactAsyncInteropLoopTest extends AbstractLoopTest
12+
{
13+
public function createLoop()
14+
{
15+
// going to use the react loop adapter as the default for now
16+
$driver = ReactDriverFactory::createFactoryFromLoop(StreamSelectLoop::class);
17+
Loop::setFactory($driver);
18+
19+
return new ReactAsyncInteropLoop();
20+
}
21+
22+
public function testRecursiveNextTick()
23+
{
24+
$this->markTestSkipped('Recursive next tick behavior does not match right now');
25+
}
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Voryx\Tests\React\EventLoop;
4+
5+
use Amp\Loop\LoopFactory;
6+
use Interop\Async\Loop;
7+
use React\Tests\EventLoop\AbstractLoopTest;
8+
use Voryx\React\EventLoop\ReactAsyncInteropLoop;
9+
10+
class ReactAsyncInteropLoopWithAmpTest extends AbstractLoopTest
11+
{
12+
public function createLoop()
13+
{
14+
Loop::setFactory(new LoopFactory());
15+
return new ReactAsyncInteropLoop();
16+
}
17+
18+
public function testRecursiveNextTick()
19+
{
20+
$this->markTestSkipped('Recursive next tick behavior does not match right now');
21+
}
22+
}

tests/bootstrap.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
$loader = @include __DIR__ . '/../vendor/autoload.php';
4+
$loader->addPsr4('React\\Tests\\EventLoop\\', __DIR__ . '/../vendor/react/event-loop/tests/');

0 commit comments

Comments
 (0)