Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 131
ExtEvLoop: Add new ExtEvLoop (PECL source ext-ev)#12
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6241c0e8e847eab2b68c6a496c63e21c0ab804d13c126a6bd8d124571cf5df8e5b0a0b34b51b65a643f27edb3b839aff0db616955a643c7af01422d40127e4f8309da525d1cf9edc3f2File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| composer.lock | ||
| phpunit.xml | ||
| vendor |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| <?php | ||
| namespace React\EventLoop; | ||
| use SplObjectStorage; | ||
| use React\EventLoop\Timer\Timer; | ||
| use React\EventLoop\Timer\TimerInterface; | ||
| use React\EventLoop\Tick\FutureTickQueue; | ||
| use React\EventLoop\Tick\NextTickQueue; | ||
| class ExtEvLoop implements LoopInterface | ||
| { | ||
| private $loop; | ||
| private $nextTickQueue; | ||
| private $futureTickQueue; | ||
| private $timers; | ||
| private $readEvents = array(); | ||
| private $writeEvents = array(); | ||
| private $running = false; | ||
| public function __construct() | ||
| { | ||
| $this->loop = new \EvLoop(); | ||
| $this->timers = new SplObjectStorage(); | ||
| $this->nextTickQueue = new NextTickQueue($this); | ||
| $this->futureTickQueue = new FutureTickQueue($this); | ||
| $this->timers = new SplObjectStorage(); | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function addReadStream($stream, callable $listener) | ||
| { | ||
| $this->addStream($stream, $listener, \Ev::READ); | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function addWriteStream($stream, callable $listener) | ||
| { | ||
| $this->addStream($stream, $listener, \Ev::WRITE); | ||
| } | ||
| /** | ||
| *{@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); | ||
| } | ||
| /** | ||
| * Wraps the listener in a callback which will pass the | ||
| * stream to the listener then registers the stream with | ||
| * the eventloop. | ||
| * | ||
| * @param resource $stream PHP Stream resource | ||
| * @param callable $listener stream callback | ||
| * @param int $flags flag bitmask | ||
| */ | ||
| private function addStream($stream, callable $listener, $flags) | ||
| { | ||
| $listener = function ($event) use ($stream, $listener){ | ||
| call_user_func($listener, $stream, $this); | ||
| }; | ||
| $event = $this->loop->io($stream, $flags, $listener); | ||
| if (($flags & \Ev::READ) === $flags){ | ||
| $this->readEvents[(int)$stream] = $event; | ||
| } elseif (($flags & \Ev::WRITE) === $flags){ | ||
| $this->writeEvents[(int)$stream] = $event; | ||
| } | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function addTimer($interval, callable $callback) | ||
| { | ||
| $timer = new Timer($this, $interval, $callback, false); | ||
| $this->setupTimer($timer); | ||
| return $timer; | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function addPeriodicTimer($interval, callable $callback) | ||
| { | ||
| $timer = new Timer($this, $interval, $callback, true); | ||
| $this->setupTimer($timer); | ||
| return $timer; | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function cancelTimer(TimerInterface $timer) | ||
| { | ||
| if (isset($this->timers[$timer])){ | ||
| /* stop EvTimer */ | ||
| $this->timers[$timer]->stop(); | ||
| /* defer timer */ | ||
| $this->nextTick(function() use ($timer){ | ||
| $this->timers->detach($timer); | ||
| }); | ||
Contributor 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. hey, this defer was added to work around a segfault, right? is it still needed? | ||
| } | ||
| } | ||
| /** | ||
| * Add timer object as | ||
| * @param TimerInterface $timer [description] | ||
| * @return [type] [description] | ||
| */ | ||
Member 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. Missing something here? :-) Seems incomplete.... ContributorAuthor 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. Looks ok to me, what strikes you as incomplete? There are some work arounds necessary with the EV extension in order to avoid segfaults across different versions of PHP, this is what your seeing here. Member 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. Hah sorry, I mean the contents of the phpdoc block :-) ContributorAuthor 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. Hah, missed that - i'll get that updated accordingly | ||
| private function setupTimer(TimerInterface $timer) | ||
| { | ||
| $callback = function () use ($timer){ | ||
| call_user_func($timer->getCallback(), $timer); | ||
| if (!$timer->isPeriodic()){ | ||
| $timer->cancel(); | ||
| } | ||
| }; | ||
| $interval = $timer->getInterval(); | ||
| $libevTimer = $this->loop->timer($interval, $interval, $callback); | ||
| $this->timers->attach($timer, $libevTimer); | ||
| return $timer; | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function isTimerActive(TimerInterface $timer) | ||
| { | ||
| return $this->timers->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() | ||
Member 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. Missing phpdoc headers with | ||
| { | ||
| $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->timers->count()){ | ||
| $this->running = false; | ||
| return; | ||
| } | ||
| $this->loop->run($flags); | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function run() | ||
| { | ||
| $this->running = true; | ||
| while($this->running){ | ||
Member 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. I'd put an empty line before this | ||
| $this->tick(); | ||
| } | ||
| } | ||
| /** | ||
| *{@inheritdoc} | ||
| */ | ||
| public function stop() | ||
| { | ||
| $this->running = false; | ||
| } | ||
| public function __destruct() | ||
| { | ||
| // mannually stop all watchers | ||
| foreach ($this->timers as $timer){ | ||
| $this->timers[$timer]->stop(); | ||
| } | ||
| foreach ($this->readEvents as $event){ | ||
| $event->stop(); | ||
| } | ||
| foreach ($this->writeEvents as $event){ | ||
| $event->stop(); | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
You should use
@inheritdocfor the phpdoc headers of methods defined in theReact\EventLoop\LoopInterface.