-
-
Notifications
You must be signed in to change notification settings - Fork 132
PeclEvLoop: Add new PeclEvLoop (PECL ext-ev) #97
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
Changes from 1 commit
4455a3b
051a4a3
0b375f7
3391da5
0e56b44
316e6a9
4c70da0
3ae1829
52e5e2e
5392032
45b7ab0
42bc95d
dac7c41
41d9d63
2ef8ff0
54710a3
79dd25c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
The existing libev driver seems to function only with a non-official, out of date libev extension for PHP. This PeclEvLoop class is a very similar clone of the LibEvLoop library but for the officially documented libev extension. Changes are mostly to constants and function parameter order.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
<?php | ||
|
||
namespace React\EventLoop; | ||
|
||
use Ev; | ||
use EvLoop; | ||
use EvIo; | ||
use EvTimer; | ||
use EvPeriodic; | ||
use React\EventLoop\Tick\FutureTickQueue; | ||
use React\EventLoop\Tick\NextTickQueue; | ||
use React\EventLoop\Timer\Timer; | ||
use React\EventLoop\Timer\TimerInterface; | ||
use SplObjectStorage; | ||
|
||
/** | ||
* @see https://bitbucket.org/osmanov/pecl-ev/overview | ||
*/ | ||
class PeclEvLoop implements LoopInterface | ||
{ | ||
private $loop; | ||
private $nextTickQueue; | ||
private $futureTickQueue; | ||
private $timerEvents; | ||
private $readEvents = []; | ||
private $writeEvents = []; | ||
private $running; | ||
|
||
public function __construct() | ||
{ | ||
$this->loop = EvLoop::defaultLoop(); | ||
$this->nextTickQueue = new NextTickQueue($this); | ||
$this->futureTickQueue = new FutureTickQueue($this); | ||
$this->timerEvents = new SplObjectStorage(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function addReadStream($stream, callable $listener) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The docblocks containing just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jsor, no problem, I can remove it, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this method implements the interface, it's explicit that the docblock is inherited. We tend to avoid docblocks since they are often redundant and become easily out of date. With type hints and return types in PHP 7, they will become even more obsolete (at least 99.9% of the time) :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jsor, ok, thank you for the explanation 😃 , I agree with your arguments (but I just looked through I removed unnecessary Btw, I think that it'll be better to cleanup the history of this PR before merging it into master (cause of a lot of little fix commits). I will do it tomorrow morning (UTC). |
||
{ | ||
$callback = function () use ($stream, $listener) { | ||
call_user_func($listener, $stream, $this); | ||
}; | ||
|
||
$event = $this->loop->io($stream, Ev::READ, $callback); | ||
|
||
$this->readEvents[(int) $stream] = $event; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function addWriteStream($stream, callable $listener) | ||
{ | ||
$callback = function () use ($stream, $listener) { | ||
call_user_func($listener, $stream, $this); | ||
}; | ||
|
||
$event = $this->loop->io($stream, Ev::WRITE, $callback); | ||
|
||
$this->writeEvents[(int) $stream] = $event; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function removeReadStream($stream) | ||
{ | ||
$key = (int) $stream; | ||
|
||
if (isset($this->readEvents[$key])) { | ||
$this->readEvents[$key]->stop(); | ||
unset($this->readEvents[$key]); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function removeWriteStream($stream) | ||
{ | ||
$key = (int) $stream; | ||
|
||
if (isset($this->writeEvents[$key])) { | ||
$this->writeEvents[$key]->stop(); | ||
unset($this->writeEvents[$key]); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function removeStream($stream) | ||
{ | ||
$this->removeReadStream($stream); | ||
$this->removeWriteStream($stream); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function addTimer($interval, callable $callback) | ||
{ | ||
$timer = new Timer($this, $interval, $callback, false); | ||
|
||
$callback = function () use ($timer) { | ||
call_user_func($timer->getCallback(), $timer); | ||
|
||
if ($this->isTimerActive($timer)) { | ||
$this->cancelTimer($timer); | ||
} | ||
}; | ||
|
||
$event = $this->loop->timer($timer->getInterval(), 0.0, $callback); | ||
$this->timerEvents->attach($timer, $event); | ||
|
||
return $timer; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function addPeriodicTimer($interval, callable $callback) | ||
{ | ||
$timer = new Timer($this, $interval, $callback, true); | ||
|
||
$callback = function () use ($timer) { | ||
call_user_func($timer->getCallback(), $timer); | ||
}; | ||
|
||
//reschedule callback should be NULL to utilize $offset and $interval params | ||
$event = $this->loop->periodic($interval, $interval, NULL, $callback); | ||
$this->timerEvents->attach($timer, $event); | ||
|
||
return $timer; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function cancelTimer(TimerInterface $timer) | ||
{ | ||
if (isset($this->timerEvents[$timer])) { | ||
$event = $this->timerEvents->get($timer); | ||
$event->stop(); | ||
$this->timerEvents->detach($timer); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function isTimerActive(TimerInterface $timer) | ||
{ | ||
return $this->timerEvents->contains($timer); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function nextTick(callable $listener) | ||
{ | ||
$this->nextTickQueue->add($listener); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function futureTick(callable $listener) | ||
{ | ||
$this->futureTickQueue->add($listener); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function tick() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note, that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
$this->nextTickQueue->tick(); | ||
|
||
$this->futureTickQueue->tick(); | ||
|
||
$this->loop->run(Ev::RUN_ONCE | Ev::RUN_NOWAIT); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function run() | ||
{ | ||
$this->running = true; | ||
|
||
while ($this->running) { | ||
$this->nextTickQueue->tick(); | ||
|
||
$this->futureTickQueue->tick(); | ||
|
||
$flags = Ev::RUN_ONCE; | ||
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) { | ||
$flags |= Ev::RUN_NOWAIT; | ||
} elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count()) { | ||
break; | ||
} | ||
|
||
$this->loop->run($flags); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function stop() | ||
{ | ||
$this->running = false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A short description would help?