Skip to content

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

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add loop driver for pecl libev extension.
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
markkimsal authored and ivkalita committed Apr 8, 2017
commit 4455a3be9426beb1bb0519cfa7c6529cbccc8ffd
2 changes: 2 additions & 0 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public static function create()
return new LibEventLoop();
} elseif (class_exists('libev\EventLoop', false)) {
return new LibEvLoop;
} elseif (class_exists('EvLoop', false)) {
return new PeclEvLoop;
} elseif (class_exists('EventBase', false)) {
return new ExtEventLoop;
}
Expand Down
217 changes: 217 additions & 0 deletions src/PeclEvLoop.php
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
Copy link
Member

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?

*/
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)
Copy link
Member

@jsor jsor Apr 20, 2017

Choose a reason for hiding this comment

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

The docblocks containing just {@inheritdoc} can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jsor, no problem, I can remove it, but {@inheritdoc} makes inheritance explicit (link to PSR-5 inheritance section). Is it a reactphp project convention?

Copy link
Member

@jsor jsor Apr 20, 2017

Choose a reason for hiding this comment

The 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) :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 LibEvLoop, StreamSelectLoop and other loops sources and there are a lot of "only @inheritdoc" PHPDocs).

I removed unnecessary @inheritdoc blocks from PeclEvLoop in 7128aaf.

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()
Copy link
Member

Choose a reason for hiding this comment

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

Note, that tick() has been removed from the interface (see #72).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jsor, oh, thank you! Fixed in c4dbd97.

{
$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;
}
}
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