diff --git a/.travis.yml b/.travis.yml index 6ef5fe32..67dc329b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,12 @@ before_script: cd libevent-0.0.5 && phpize && ./configure && make && sudo make install; echo "extension=libevent.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi" + - sh -c " if [ \"\$(php --re ev | grep 'does not exist')\" != '' ]; then + git clone https://bitbucket.org/osmanov/pecl-ev.git; + cd pecl-ev; + phpize && ./configure --enable-ev && make && make install; + echo "extension=ev.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; + fi" - composer self-update - composer install --dev --prefer-source diff --git a/src/React/EventLoop/EvLoop.php b/src/React/EventLoop/EvLoop.php new file mode 100644 index 00000000..19306257 --- /dev/null +++ b/src/React/EventLoop/EvLoop.php @@ -0,0 +1,153 @@ +loop = new \EvLoop(); + $this->timers = new SplObjectStorage(); + } + + public function addReadStream($stream, $listener) + { + $this->addStream($stream, $listener, \Ev::READ); + } + + public function addWriteStream($stream, $listener) + { + $this->addStream($stream, $listener, \Ev::WRITE); + } + + public function removeReadStream($stream) + { + $this->readEvents[(int)$stream]->stop(); + unset($this->readEvents[(int)$stream]); + } + + public function removeWriteStream($stream) + { + $this->writeEvents[(int)$stream]->stop(); + unset($this->writeEvents[(int)$stream]); + } + + public function removeStream($stream) + { + if (isset($this->readEvents[(int)$stream])) { + $this->removeReadStream($stream); + } + + if (isset($this->writeEvents[(int)$stream])) { + $this->removeWriteStream($stream); + } + } + + private function addStream($stream, $listener, $flags) + { + $listener = $this->wrapStreamListener($stream, $listener, $flags); + $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; + } + } + + private function wrapStreamListener($stream, $listener, $flags) + { + if (($flags & \Ev::READ) === $flags) { + $removeCallback = array($this, 'removeReadStream'); + } elseif (($flags & \Ev::WRITE) === $flags) { + $removeCallback = array($this, 'removeWriteStream'); + } + + return function ($event) use ($stream, $listener, $removeCallback) { + if (feof($stream)) { + call_user_func($removeCallback, $stream); + + return; + } + + call_user_func($listener, $stream); + }; + } + + public function addTimer($interval, $callback) + { + $timer = new Timer($this, $interval, $callback, false); + $this->setupTimer($timer); + + return $timer; + } + + public function addPeriodicTimer($interval, $callback) + { + $timer = new Timer($this, $interval, $callback, true); + $this->setupTimer($timer); + + return $timer; + } + + public function cancelTimer(TimerInterface $timer) + { + if (isset($this->timers[$timer])) { + $this->timers[$timer]->stop(); + $this->timers->detach($timer); + } + } + + private function setupTimer(TimerInterface $timer) + { + $dummyCallback = function () {}; + $interval = $timer->getInterval(); + + if ($timer->isPeriodic()) { + $libevTimer = $this->loop->timer($interval, $interval, $dummyCallback); + } else { + $libevTimer = $this->loop->timer($interval, $dummyCallback); + } + + $libevTimer->setCallback(function () use ($timer) { + call_user_func($timer->getCallback(), $timer); + + if (!$timer->isPeriodic()) { + $timer->cancel(); + } + }); + + $this->timers->attach($timer, $libevTimer); + + return $timer; + } + + public function isTimerActive(TimerInterface $timer) + { + return $this->timers->contains($timer); + } + + public function tick() + { + $this->loop->run(\Ev::RUN_ONCE); + } + + public function run() + { + $this->loop->run(); + } + + public function stop() + { + $this->loop->stop(); + } +} diff --git a/tests/React/Tests/EventLoop/EvLoopTest.php b/tests/React/Tests/EventLoop/EvLoopTest.php new file mode 100644 index 00000000..d7abb454 --- /dev/null +++ b/tests/React/Tests/EventLoop/EvLoopTest.php @@ -0,0 +1,22 @@ +markTestSkipped('ev tests skipped because pecl/ev is not installed.'); + } + + return new EvLoop(); + } + + public function testEvConstructor() + { + $loop = new EvLoop(); + } +}
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: