From c4f0e4511571260b9c61afd8dbc6ad073af91910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sun, 14 Jan 2018 14:52:47 +0100 Subject: [PATCH] [RFC] Improve compatibility with legacy versions --- .travis.yml | 4 ++ README.md | 4 +- composer.json | 2 +- src/ExtEventLoop.php | 31 +++++----- src/ExtLibevLoop.php | 19 +++--- src/ExtLibeventLoop.php | 34 ++++++----- src/SignalsHandler.php | 4 +- src/StreamSelectLoop.php | 8 +-- tests/AbstractLoopTest.php | 105 +++++++++++++++++++-------------- tests/StreamSelectLoopTest.php | 20 ++++--- travis-init.sh | 4 +- 11 files changed, 135 insertions(+), 100 deletions(-) diff --git a/.travis.yml b/.travis.yml index b51dcb9b..7af713a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: +# - 5.3 # requires old distro, see below - 5.4 - 5.5 - 5.6 @@ -13,6 +14,9 @@ php: dist: trusty matrix: + include: + - php: 5.3 + dist: precise allow_failures: - php: hhvm diff --git a/README.md b/README.md index 7d7e0f38..7a30ec15 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ A `stream_select()` based event loop. This uses the [`stream_select()`](http://php.net/manual/en/function.stream-select.php) function and is the only implementation which works out of the box with PHP. -This event loop works out of the box on PHP 5.4 through PHP 7+ and HHVM. +This event loop works out of the box on PHP 5.3 through PHP 7+ and HHVM. This means that no installation is required and this library works on all platforms and supported PHP versions. Accordingly, the [`Factory`](#factory) will use this event loop by default if @@ -574,7 +574,7 @@ $ composer require react/event-loop ``` This project aims to run on any platform and thus does not require any PHP -extensions and supports running on legacy PHP 5.4 through current PHP 7+ and +extensions and supports running on legacy PHP 5.3 through current PHP 7+ and HHVM. It's *highly recommended to use PHP 7+* for this project. diff --git a/composer.json b/composer.json index ad14cf4b..05afe65a 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": ["event-loop", "asynchronous"], "license": "MIT", "require": { - "php": ">=5.4.0" + "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "~4.8.35 || ^5.7 || ^6.4" diff --git a/src/ExtEventLoop.php b/src/ExtEventLoop.php index 53bbc974..4146fc18 100644 --- a/src/ExtEventLoop.php +++ b/src/ExtEventLoop.php @@ -26,15 +26,15 @@ final class ExtEventLoop implements LoopInterface private $timerCallback; private $timerEvents; private $streamCallback; - private $readEvents = []; - private $writeEvents = []; - private $readListeners = []; - private $writeListeners = []; - private $readRefs = []; - private $writeRefs = []; + private $readEvents = array(); + private $writeEvents = array(); + private $readListeners = array(); + private $writeListeners = array(); + private $readRefs = array(); + private $writeRefs = array(); private $running; private $signals; - private $signalEvents = []; + private $signalEvents = array(); public function __construct(EventBaseConfig $config = null) { @@ -215,10 +215,11 @@ private function scheduleTimer(TimerInterface $timer) */ private function createTimerCallback() { - $this->timerCallback = function ($_, $__, $timer) { + $timers = $this->timerEvents; + $this->timerCallback = function ($_, $__, $timer) use ($timers) { call_user_func($timer->getCallback(), $timer); - if (!$timer->isPeriodic() && $this->timerEvents->contains($timer)) { + if (!$timer->isPeriodic() && $timers->contains($timer)) { $this->cancelTimer($timer); } }; @@ -233,15 +234,17 @@ private function createTimerCallback() */ private function createStreamCallback() { - $this->streamCallback = function ($stream, $flags) { + $read =& $this->readListeners; + $write =& $this->writeListeners; + $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { $key = (int) $stream; - if (Event::READ === (Event::READ & $flags) && isset($this->readListeners[$key])) { - call_user_func($this->readListeners[$key], $stream); + if (Event::READ === (Event::READ & $flags) && isset($read[$key])) { + call_user_func($read[$key], $stream); } - if (Event::WRITE === (Event::WRITE & $flags) && isset($this->writeListeners[$key])) { - call_user_func($this->writeListeners[$key], $stream); + if (Event::WRITE === (Event::WRITE & $flags) && isset($write[$key])) { + call_user_func($write[$key], $stream); } }; } diff --git a/src/ExtLibevLoop.php b/src/ExtLibevLoop.php index 587bb044..9c679895 100644 --- a/src/ExtLibevLoop.php +++ b/src/ExtLibevLoop.php @@ -28,11 +28,11 @@ final class ExtLibevLoop implements LoopInterface private $loop; private $futureTickQueue; private $timerEvents; - private $readEvents = []; - private $writeEvents = []; + private $readEvents = array(); + private $writeEvents = array(); private $running; private $signals; - private $signalEvents = []; + private $signalEvents = array(); public function __construct() { @@ -100,11 +100,13 @@ public function addTimer($interval, $callback) { $timer = new Timer( $interval, $callback, false); - $callback = function () use ($timer) { + $that = $this; + $timers = $this->timerEvents; + $callback = function () use ($timer, $timers, $that) { call_user_func($timer->getCallback(), $timer); - if ($this->timerEvents->contains($timer)) { - $this->cancelTimer($timer); + if ($timers->contains($timer)) { + $that->cancelTimer($timer); } }; @@ -148,8 +150,9 @@ public function addSignal($signal, $listener) $this->signals->add($signal, $listener); if (!isset($this->signalEvents[$signal])) { - $this->signalEvents[$signal] = new SignalEvent(function () use ($signal) { - $this->signals->call($signal); + $signals = $this->signals; + $this->signalEvents[$signal] = new SignalEvent(function () use ($signals, $signal) { + $signals->call($signal); }, $signal); $this->loop->add($this->signalEvents[$signal]); } diff --git a/src/ExtLibeventLoop.php b/src/ExtLibeventLoop.php index da181a28..5bc265e2 100644 --- a/src/ExtLibeventLoop.php +++ b/src/ExtLibeventLoop.php @@ -42,13 +42,13 @@ final class ExtLibeventLoop implements LoopInterface private $timerCallback; private $timerEvents; private $streamCallback; - private $readEvents = []; - private $writeEvents = []; - private $readListeners = []; - private $writeListeners = []; + private $readEvents = array(); + private $writeEvents = array(); + private $readListeners = array(); + private $writeListeners = array(); private $running; private $signals; - private $signalEvents = []; + private $signalEvents = array(); public function __construct() { @@ -228,24 +228,26 @@ private function scheduleTimer(TimerInterface $timer) */ private function createTimerCallback() { - $this->timerCallback = function ($_, $__, $timer) { + $that = $this; + $timers = $this->timerEvents; + $this->timerCallback = function ($_, $__, $timer) use ($timers, $that) { call_user_func($timer->getCallback(), $timer); // Timer already cancelled ... - if (!$this->timerEvents->contains($timer)) { + if (!$timers->contains($timer)) { return; } // Reschedule periodic timers ... if ($timer->isPeriodic()) { event_add( - $this->timerEvents[$timer], - $timer->getInterval() * self::MICROSECONDS_PER_SECOND + $timers[$timer], + $timer->getInterval() * ExtLibeventLoop::MICROSECONDS_PER_SECOND ); // Clean-up one shot timers ... } else { - $this->cancelTimer($timer); + $that->cancelTimer($timer); } }; } @@ -259,15 +261,17 @@ private function createTimerCallback() */ private function createStreamCallback() { - $this->streamCallback = function ($stream, $flags) { + $read =& $this->readListeners; + $write =& $this->writeListeners; + $this->streamCallback = function ($stream, $flags) use (&$read, &$write) { $key = (int) $stream; - if (EV_READ === (EV_READ & $flags) && isset($this->readListeners[$key])) { - call_user_func($this->readListeners[$key], $stream); + if (EV_READ === (EV_READ & $flags) && isset($read[$key])) { + call_user_func($read[$key], $stream); } - if (EV_WRITE === (EV_WRITE & $flags) && isset($this->writeListeners[$key])) { - call_user_func($this->writeListeners[$key], $stream); + if (EV_WRITE === (EV_WRITE & $flags) && isset($write[$key])) { + call_user_func($write[$key], $stream); } }; } diff --git a/src/SignalsHandler.php b/src/SignalsHandler.php index 2614e03c..523e1ca1 100644 --- a/src/SignalsHandler.php +++ b/src/SignalsHandler.php @@ -7,12 +7,12 @@ */ final class SignalsHandler { - private $signals = []; + private $signals = array(); public function add($signal, $listener) { if (!isset($this->signals[$signal])) { - $this->signals[$signal] = []; + $this->signals[$signal] = array(); } if (in_array($listener, $this->signals[$signal])) { diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 55bb1b8a..e82e9e47 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -56,10 +56,10 @@ final class StreamSelectLoop implements LoopInterface private $futureTickQueue; private $timers; - private $readStreams = []; - private $readListeners = []; - private $writeStreams = []; - private $writeListeners = []; + private $readStreams = array(); + private $readListeners = array(); + private $writeStreams = array(); + private $writeListeners = array(); private $running; private $pcntl = false; private $signals; diff --git a/tests/AbstractLoopTest.php b/tests/AbstractLoopTest.php index 6cac6eb1..2a30b48c 100644 --- a/tests/AbstractLoopTest.php +++ b/tests/AbstractLoopTest.php @@ -82,14 +82,16 @@ private function subAddReadStreamReceivesDataFromStreamReference() fwrite($input, 'hello'); fclose($input); - $this->loop->addReadStream($output, function ($output) { + $loop = $this->loop; + $received =& $this->received; + $loop->addReadStream($output, function ($output) use ($loop, &$received) { $chunk = fread($output, 1024); if ($chunk === '') { - $this->received .= 'X'; - $this->loop->removeReadStream($output); + $received .= 'X'; + $loop->removeReadStream($output); fclose($output); } else { - $this->received .= '[' . $chunk . ']'; + $received .= '[' . $chunk . ']'; } }); } @@ -194,9 +196,10 @@ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesEndsLoop() $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $this->loop->addReadStream($stream, function ($stream) { - $this->loop->removeReadStream($stream); - $this->loop->removeWriteStream($stream); + $loop = $this->loop; + $loop->addReadStream($stream, function ($stream) use ($loop) { + $loop->removeReadStream($stream); + $loop->removeWriteStream($stream); fclose($stream); }); @@ -216,14 +219,15 @@ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesOnEndOfFil $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $this->loop->addReadStream($stream, function ($stream) { + $loop = $this->loop; + $loop->addReadStream($stream, function ($stream) use ($loop) { $data = fread($stream, 1024); if ($data !== '') { return; } - $this->loop->removeReadStream($stream); - $this->loop->removeWriteStream($stream); + $loop->removeReadStream($stream); + $loop->removeWriteStream($stream); fclose($stream); }); @@ -246,9 +250,10 @@ public function testRemoveReadAndWriteStreamFromLoopWithClosingResourceEndsLoop( $this->loop->addWriteStream($stream, function () { }); // remove stream when the stream is readable (closes) - $this->loop->addReadStream($stream, function ($stream) { - $this->loop->removeReadStream($stream); - $this->loop->removeWriteStream($stream); + $loop = $this->loop; + $loop->addReadStream($stream, function ($stream) use ($loop) { + $loop->removeReadStream($stream); + $loop->removeWriteStream($stream); fclose($stream); }); @@ -304,16 +309,18 @@ public function stopShouldStopRunningLoop() public function testStopShouldPreventRunFromBlocking() { + $that = $this; $this->loop->addTimer( 1, - function () { - $this->fail('Timer was executed.'); + function () use ($that) { + $that->fail('Timer was executed.'); } ); + $loop = $this->loop; $this->loop->futureTick( - function () { - $this->loop->stop(); + function () use ($loop) { + $loop->stop(); } ); @@ -338,9 +345,10 @@ public function testIgnoreRemovedCallback() }); // this callback would have to be called as well, but the first stream already removed us - $loop->addReadStream($input2, function () use (& $called) { + $that = $this; + $loop->addReadStream($input2, function () use (& $called, $that) { if ($called) { - $this->fail('Callback 2 must not be called after callback 1 was called'); + $that->fail('Callback 2 must not be called after callback 1 was called'); } }); @@ -354,9 +362,10 @@ public function testIgnoreRemovedCallback() public function testFutureTickEventGeneratedByFutureTick() { + $loop = $this->loop; $this->loop->futureTick( - function () { - $this->loop->futureTick( + function () use ($loop) { + $loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -412,18 +421,19 @@ public function testRecursiveFutureTick() { list ($stream) = $this->createSocketPair(); + $loop = $this->loop; $this->loop->addWriteStream( $stream, - function () use ($stream) { + function () use ($stream, $loop) { echo 'stream' . PHP_EOL; - $this->loop->removeWriteStream($stream); + $loop->removeWriteStream($stream); } ); $this->loop->futureTick( - function () { + function () use ($loop) { echo 'future-tick-1' . PHP_EOL; - $this->loop->futureTick( + $loop->futureTick( function () { echo 'future-tick-2' . PHP_EOL; } @@ -440,11 +450,12 @@ public function testRunWaitsForFutureTickEvents() { list ($stream) = $this->createSocketPair(); + $loop = $this->loop; $this->loop->addWriteStream( $stream, - function () use ($stream) { - $this->loop->removeWriteStream($stream); - $this->loop->futureTick( + function () use ($stream, $loop) { + $loop->removeWriteStream($stream); + $loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -459,10 +470,11 @@ function () { public function testFutureTickEventGeneratedByTimer() { + $loop = $this->loop; $this->loop->addTimer( 0.001, - function () { - $this->loop->futureTick( + function () use ($loop) { + $loop->futureTick( function () { echo 'future-tick' . PHP_EOL; } @@ -496,11 +508,12 @@ public function testSignal() $calledShouldNot = false; }); - $this->loop->addSignal(SIGUSR1, $func1 = function () use (&$func1, &$func2, &$called, $timer) { + $loop = $this->loop; + $this->loop->addSignal(SIGUSR1, $func1 = function () use (&$func1, &$func2, &$called, $timer, $loop) { $called = true; - $this->loop->removeSignal(SIGUSR1, $func1); - $this->loop->removeSignal(SIGUSR2, $func2); - $this->loop->cancelTimer($timer); + $loop->removeSignal(SIGUSR1, $func1); + $loop->removeSignal(SIGUSR2, $func2); + $loop->cancelTimer($timer); }); $this->loop->futureTick(function () { @@ -527,8 +540,9 @@ public function testSignalMultipleUsagesForTheSameListener() $this->loop->addTimer(0.4, function () { posix_kill(posix_getpid(), SIGUSR1); }); - $this->loop->addTimer(0.9, function () use (&$func) { - $this->loop->removeSignal(SIGUSR1, $func); + $loop = $this->loop; + $this->loop->addTimer(0.9, function () use (&$func, $loop) { + $loop->removeSignal(SIGUSR1, $func); }); $this->loop->run(); @@ -538,11 +552,12 @@ public function testSignalMultipleUsagesForTheSameListener() public function testSignalsKeepTheLoopRunning() { + $loop = $this->loop; $function = function () {}; $this->loop->addSignal(SIGUSR1, $function); - $this->loop->addTimer(1.5, function () use ($function) { - $this->loop->removeSignal(SIGUSR1, $function); - $this->loop->stop(); + $this->loop->addTimer(1.5, function () use ($function, $loop) { + $loop->removeSignal(SIGUSR1, $function); + $loop->stop(); }); $this->assertRunSlowerThan(1.5); @@ -550,10 +565,11 @@ public function testSignalsKeepTheLoopRunning() public function testSignalsKeepTheLoopRunningAndRemovingItStopsTheLoop() { + $loop = $this->loop; $function = function () {}; $this->loop->addSignal(SIGUSR1, $function); - $this->loop->addTimer(1.5, function () use ($function) { - $this->loop->removeSignal(SIGUSR1, $function); + $this->loop->addTimer(1.5, function () use ($function, $loop) { + $loop->removeSignal(SIGUSR1, $function); }); $this->assertRunFasterThan(1.6); @@ -568,9 +584,10 @@ public function testTimerIntervalCanBeFarInFuture() $timer = $this->loop->addTimer(PHP_INT_MAX, function () { }); // remove stream and timer when the stream is readable (closes) - $this->loop->addReadStream($stream, function ($stream) use ($timer) { - $this->loop->removeReadStream($stream); - $this->loop->cancelTimer($timer); + $loop = $this->loop; + $this->loop->addReadStream($stream, function ($stream) use ($timer, $loop) { + $loop->removeReadStream($stream); + $loop->cancelTimer($timer); }); $this->assertRunFasterThan($this->tickTimeout); diff --git a/tests/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index 87bbbe69..bd19e1cd 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -39,11 +39,11 @@ public function testStreamSelectTimeoutEmulation() public function signalProvider() { - return [ - ['SIGUSR1'], - ['SIGHUP'], - ['SIGTERM'], - ]; + return array( + array('SIGUSR1'), + array('SIGHUP'), + array('SIGTERM'), + ); } /** @@ -60,8 +60,9 @@ public function testSignalInterruptNoStream($signal) $check = $this->loop->addPeriodicTimer(0.01, function() { pcntl_signal_dispatch(); }); - $this->loop->addTimer(0.1, function () use ($check) { - $this->loop->cancelTimer($check); + $loop = $this->loop; + $loop->addTimer(0.1, function () use ($check, $loop) { + $loop->cancelTimer($check); }); $handled = false; @@ -92,12 +93,13 @@ public function testSignalInterruptWithStream($signal) }); // add stream to the loop + $loop = $this->loop; list($writeStream, $readStream) = $this->createSocketPair(); - $this->loop->addReadStream($readStream, function ($stream) { + $loop->addReadStream($readStream, function ($stream) use ($loop) { /** @var $loop LoopInterface */ $read = fgets($stream); if ($read === "end loop\n") { - $this->loop->stop(); + $loop->stop(); } }); $this->loop->addTimer(0.1, function() use ($writeStream) { diff --git a/travis-init.sh b/travis-init.sh index c8c8b55d..06f853fe 100755 --- a/travis-init.sh +++ b/travis-init.sh @@ -6,7 +6,9 @@ if [[ "$TRAVIS_PHP_VERSION" != "hhvm" && "$TRAVIS_PHP_VERSION" != "hhvm-nightly" ]]; then # install 'event' PHP extension - echo "yes" | pecl install event + if [[ "$TRAVIS_PHP_VERSION" != "5.3" ]]; then + echo "yes" | pecl install event + fi # install 'libevent' PHP extension (does not support php 7) if [[ "$TRAVIS_PHP_VERSION" != "7.0" && 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