mirror of
https://github.com/danog/amp.git
synced 2025-01-22 05:11:42 +01:00
Merge branch 'uv'
This commit is contained in:
commit
5079bb3f13
35
.travis.yml
35
.travis.yml
@ -6,13 +6,36 @@ php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- nightly
|
||||
|
||||
install:
|
||||
- php -r 'exit((int) (PHP_MAJOR_VERSION < 7));' || (yes "" | pecl install "channel://pecl.php.net/libevent-0.1.0")
|
||||
- php -r 'exit((int) (PHP_MAJOR_VERSION < 7));' || (yes "" | pecl install ev)
|
||||
- php -r 'exit((int) (PHP_MAJOR_VERSION >= 7));' || (mkdir libuv && (curl -L https://github.com/libuv/libuv/archive/v1.6.1.tar.gz | tar xzf -) && cd libuv-1.6.1 && ./autogen.sh && ./configure --prefix=$(readlink -f `pwd`/../libuv) && make && make install && cd ..)
|
||||
- php -r 'exit((int) (PHP_MAJOR_VERSION >= 7));' || (git clone https://github.com/bwoebi/php-uv && cd php-uv && phpize && ./configure --with-uv=$(readlink -f `pwd`/../libuv) && make install && (echo "extension = uv.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini) && cd ..)
|
||||
- if [ "$TRAVIS_PHP_VERSION" != "5.5" ] && [ "$TRAVIS_PHP_VERSION" != "5.6" ] ; then
|
||||
git clone https://github.com/libuv/libuv;
|
||||
pushd libuv;
|
||||
git checkout $(git describe --tags);
|
||||
./autogen.sh;
|
||||
./configure --prefix=$(dirname `pwd`)/libuv-install;
|
||||
make;
|
||||
make install;
|
||||
popd;
|
||||
git clone https://github.com/bwoebi/php-uv.git;
|
||||
pushd php-uv;
|
||||
phpize;
|
||||
./configure --with-uv=$(dirname `pwd`)/libuv-install;
|
||||
make;
|
||||
make install;
|
||||
popd;
|
||||
echo "extension=uv.so" >> "$(php -r 'echo php_ini_loaded_file();')";
|
||||
fi;
|
||||
- curl -LS https://pecl.php.net/get/ev | tar -xz;
|
||||
pushd ev-*;
|
||||
phpize;
|
||||
./configure;
|
||||
make;
|
||||
make install;
|
||||
popd;
|
||||
echo "extension=ev.so" >> "$(php -r 'echo php_ini_loaded_file();')";
|
||||
- composer self-update
|
||||
- composer install --no-interaction --prefer-source
|
||||
|
||||
@ -22,8 +45,8 @@ script:
|
||||
|
||||
after_script:
|
||||
- composer require satooshi/php-coveralls dev-master
|
||||
- php vendor/bin/coveralls -v
|
||||
|
||||
- php vendor/bin/coveralls -v --exclude-no-stmt
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
@ -11,7 +11,7 @@
|
||||
"homepage": "http://amphp.org",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"async-interop/event-loop": "^0.3"
|
||||
"async-interop/event-loop": "dev-master"
|
||||
},
|
||||
"require-dev": {
|
||||
"async-interop/event-loop-test": "dev-master",
|
||||
|
@ -364,13 +364,15 @@ abstract class Loop extends Driver {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setErrorHandler(callable $callback = null) {
|
||||
$previous = $this->errorHandler;
|
||||
$this->errorHandler = $callback;
|
||||
return $previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function info() {
|
||||
public function getInfo() {
|
||||
$watchers = [
|
||||
"referenced" => 0,
|
||||
"unreferenced" => 0,
|
||||
|
279
lib/UvLoop.php
Normal file
279
lib/UvLoop.php
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Loop;
|
||||
|
||||
use Amp\Loop\Internal\Watcher;
|
||||
|
||||
class UvLoop extends Loop {
|
||||
/**
|
||||
* A uv_loop resource created with uv_loop_new()
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
private $handle;
|
||||
|
||||
/**
|
||||
* @var resource[]
|
||||
*/
|
||||
private $events = [];
|
||||
|
||||
/**
|
||||
* @var \Amp\Loop\Internal\Watcher[]|\Amp\Loop\Internal\Watcher[][]
|
||||
*/
|
||||
private $watchers = [];
|
||||
|
||||
/**
|
||||
* @var resource[]
|
||||
*/
|
||||
private $read = [];
|
||||
|
||||
/**
|
||||
* @var resource[]
|
||||
*/
|
||||
private $write = [];
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $ioCallback;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $timerCallback;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $signalCallback;
|
||||
|
||||
public static function supported() {
|
||||
return \extension_loaded("uv");
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->handle = \uv_loop_new();
|
||||
|
||||
$this->ioCallback = function ($event, $status, $events, $resource) {
|
||||
switch ($status) {
|
||||
case 0: // OK
|
||||
break;
|
||||
|
||||
// If $status is a severe error, stop the poll and throw an exception.
|
||||
case \UV::EACCES:
|
||||
case \UV::EBADF:
|
||||
case \UV::EINVAL:
|
||||
case \UV::ENOTSOCK:
|
||||
throw new \RuntimeException(
|
||||
\sprintf("UV_%s: %s", \uv_err_name($status), \ucfirst(\uv_strerror($status)))
|
||||
);
|
||||
|
||||
default: // Ignore other (probably) trivial warnings and continuing polling.
|
||||
return;
|
||||
}
|
||||
|
||||
$watchers = $this->watchers[(int) $event];
|
||||
|
||||
foreach ($watchers as $watcher) {
|
||||
$callback = $watcher->callback;
|
||||
$callback($watcher->id, $resource, $watcher->data);
|
||||
}
|
||||
};
|
||||
|
||||
$this->timerCallback = function ($event) {
|
||||
$watcher = $this->watchers[(int) $event];
|
||||
|
||||
if ($watcher->type & Watcher::DELAY) {
|
||||
$this->cancel($watcher->id);
|
||||
}
|
||||
|
||||
$callback = $watcher->callback;
|
||||
$callback($watcher->id, $watcher->data);
|
||||
};
|
||||
|
||||
$this->signalCallback = function ($event, $signo) {
|
||||
$watcher = $this->watchers[(int) $event];
|
||||
|
||||
$callback = $watcher->callback;
|
||||
$callback($watcher->id, $signo, $watcher->data);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function stop() {
|
||||
\uv_stop($this->handle);
|
||||
parent::stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function dispatch($blocking) {
|
||||
\uv_run($this->handle, $blocking ? \UV::RUN_ONCE : \UV::RUN_NOWAIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function activate(array $watchers) {
|
||||
foreach ($watchers as $watcher) {
|
||||
$id = $watcher->id;
|
||||
|
||||
switch ($watcher->type) {
|
||||
case Watcher::READABLE:
|
||||
$streamId = (int) $watcher->value;
|
||||
|
||||
if (isset($this->read[$streamId])) {
|
||||
$event = $this->read[$streamId];
|
||||
} elseif (isset($this->events[$id])) {
|
||||
$event = $this->read[$streamId] = $this->events[$id];
|
||||
} else {
|
||||
$event = $this->read[$streamId] = \uv_poll_init_socket($this->handle, $watcher->value);
|
||||
}
|
||||
|
||||
$this->events[$id] = $event;
|
||||
$this->watchers[(int) $event][$id] = $watcher;
|
||||
|
||||
if (!\uv_is_active($event)) {
|
||||
\uv_poll_start($event, \UV::READABLE, $this->ioCallback);
|
||||
}
|
||||
break;
|
||||
|
||||
case Watcher::WRITABLE:
|
||||
$streamId = (int) $watcher->value;
|
||||
|
||||
if (isset($this->write[$streamId])) {
|
||||
$event = $this->write[$streamId];
|
||||
} elseif (isset($this->events[$id])) {
|
||||
$event = $this->write[$streamId] = $this->events[$id];
|
||||
} else {
|
||||
$event = $this->write[$streamId] = \uv_poll_init_socket($this->handle, $watcher->value);
|
||||
}
|
||||
|
||||
$this->events[$id] = $event;
|
||||
$this->watchers[(int) $event][$id] = $watcher;
|
||||
|
||||
|
||||
if (!\uv_is_active($event)) {
|
||||
\uv_poll_start($event, \UV::WRITABLE, $this->ioCallback);
|
||||
}
|
||||
break;
|
||||
|
||||
case Watcher::DELAY:
|
||||
case Watcher::REPEAT:
|
||||
if (isset($this->events[$id])) {
|
||||
$event = $this->events[$id];
|
||||
} else {
|
||||
$event = $this->events[$id] = \uv_timer_init($this->handle);
|
||||
$this->watchers[(int) $event] = $watcher;
|
||||
}
|
||||
|
||||
\uv_timer_start(
|
||||
$event,
|
||||
$watcher->value,
|
||||
$watcher->type & Watcher::REPEAT ? $watcher->value : 0,
|
||||
$this->timerCallback
|
||||
);
|
||||
break;
|
||||
|
||||
case Watcher::SIGNAL:
|
||||
if (isset($this->events[$id])) {
|
||||
$event = $this->events[$id];
|
||||
} else {
|
||||
$event = $this->events[$id] = \uv_signal_init($this->handle);
|
||||
$this->watchers[(int) $event] = $watcher;
|
||||
}
|
||||
|
||||
\uv_signal_start($event, $this->signalCallback, $watcher->value);
|
||||
break;
|
||||
|
||||
default: throw new \DomainException("Unknown watcher type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deactivate(Watcher $watcher) {
|
||||
$id = $watcher->id;
|
||||
|
||||
if (!isset($this->events[$id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = $this->events[$id];
|
||||
$eventId = (int) $event;
|
||||
|
||||
switch ($watcher->type) {
|
||||
case Watcher::READABLE:
|
||||
unset($this->watchers[$eventId][$id]);
|
||||
|
||||
if (empty($this->watchers[$eventId])) {
|
||||
unset($this->watchers[$eventId]);
|
||||
unset($this->read[(int) $watcher->value]);
|
||||
if (\uv_is_active($event)) {
|
||||
\uv_poll_stop($event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Watcher::WRITABLE:
|
||||
unset($this->watchers[$eventId][$id]);
|
||||
|
||||
if (empty($this->watchers[$eventId])) {
|
||||
unset($this->watchers[$eventId]);
|
||||
unset($this->write[(int) $watcher->value]);
|
||||
if (\uv_is_active($event)) {
|
||||
\uv_poll_stop($event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Watcher::DELAY:
|
||||
case Watcher::REPEAT:
|
||||
unset($this->watchers[$eventId]);
|
||||
if (\uv_is_active($event)) {
|
||||
\uv_timer_stop($event);
|
||||
}
|
||||
break;
|
||||
|
||||
case Watcher::SIGNAL:
|
||||
unset($this->watchers[$eventId]);
|
||||
if (\uv_is_active($event)) {
|
||||
\uv_signal_stop($event);
|
||||
}
|
||||
break;
|
||||
|
||||
default: throw new \DomainException("Unknown watcher type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function cancel($watcherIdentifier) {
|
||||
parent::cancel($watcherIdentifier);
|
||||
|
||||
if (!isset($this->events[$watcherIdentifier])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event = $this->events[$watcherIdentifier];
|
||||
|
||||
if (empty($this->watchers[(int) $event])) {
|
||||
\uv_close($event);
|
||||
}
|
||||
|
||||
unset($this->events[$watcherIdentifier]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getHandle() {
|
||||
return $this->handle;
|
||||
}
|
||||
}
|
18
test/UvLoopTest.php
Normal file
18
test/UvLoopTest.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test\Loop;
|
||||
|
||||
use Amp\Loop\UvLoop;
|
||||
use Interop\Async\Loop\DriverFactory;
|
||||
use Interop\Async\Loop\Test;
|
||||
|
||||
class UvLoopTest extends Test {
|
||||
public function getFactory() {
|
||||
$factory = $this->getMockBuilder(DriverFactory::class)->getMock();
|
||||
|
||||
$factory->method('create')
|
||||
->willReturn(new UvLoop());
|
||||
|
||||
return $factory;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user