mirror of
https://github.com/danog/parallel.git
synced 2024-11-26 12:24:40 +01:00
Apply Amp's code style
This commit is contained in:
parent
1f637cfc6f
commit
2e9a29ae1c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.php_cs.cache
|
||||
.vagrant
|
||||
build
|
||||
composer.lock
|
||||
|
40
.php_cs.dist
Normal file
40
.php_cs.dist
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules([
|
||||
"@PSR1" => true,
|
||||
"@PSR2" => true,
|
||||
"braces" => [
|
||||
"allow_single_line_closure" => true,
|
||||
"position_after_functions_and_oop_constructs" => "same",
|
||||
],
|
||||
"array_syntax" => ["syntax" => "short"],
|
||||
"cast_spaces" => true,
|
||||
"combine_consecutive_unsets" => true,
|
||||
"function_to_constant" => true,
|
||||
"no_multiline_whitespace_before_semicolons" => true,
|
||||
"no_unused_imports" => true,
|
||||
"no_useless_else" => true,
|
||||
"no_useless_return" => true,
|
||||
"no_whitespace_before_comma_in_array" => true,
|
||||
"no_whitespace_in_blank_line" => true,
|
||||
"non_printable_character" => true,
|
||||
"normalize_index_brace" => true,
|
||||
"ordered_imports" => true,
|
||||
"php_unit_construct" => true,
|
||||
"php_unit_dedicate_assert" => true,
|
||||
"php_unit_fqcn_annotation" => true,
|
||||
"phpdoc_summary" => true,
|
||||
"phpdoc_types" => true,
|
||||
"psr4" => true,
|
||||
"return_type_declaration" => ["space_before" => "none"],
|
||||
"short_scalar_cast" => true,
|
||||
"single_blank_line_before_namespace" => true,
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->in(__DIR__ . "/example")
|
||||
->in(__DIR__ . "/lib")
|
||||
->in(__DIR__ . "/test")
|
||||
);
|
45
Makefile
Normal file
45
Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
PHP_BIN := php
|
||||
COMPOSER_BIN := composer
|
||||
|
||||
COVERAGE = coverage
|
||||
SRCS = lib test
|
||||
|
||||
find_php_files = $(shell find $(1) -type f -name "*.php")
|
||||
src = $(foreach d,$(SRCS),$(call find_php_files,$(d)))
|
||||
|
||||
.PHONY: test
|
||||
test: setup phpunit code-style
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-coverage clean-vendor
|
||||
|
||||
.PHONY: clean-coverage
|
||||
clean-coverage:
|
||||
test ! -e coverage || rm -r coverage
|
||||
|
||||
.PHONY: clean-vendor
|
||||
clean-vendor:
|
||||
test ! -e vendor || rm -r vendor
|
||||
|
||||
.PHONY: setup
|
||||
setup: vendor/autoload.php
|
||||
|
||||
.PHONY: deps-update
|
||||
deps-update:
|
||||
$(COMPOSER_BIN) update
|
||||
|
||||
.PHONY: phpunit
|
||||
phpunit: setup
|
||||
$(PHP_BIN) vendor/bin/phpunit
|
||||
|
||||
.PHONY: code-style
|
||||
code-style: setup
|
||||
PHP_CS_FIXER_IGNORE_ENV=1 $(PHP_BIN) vendor/bin/php-cs-fixer --diff -v fix
|
||||
|
||||
composer.lock: composer.json
|
||||
$(COMPOSER_BIN) install
|
||||
touch $@
|
||||
|
||||
vendor/autoload.php: composer.lock
|
||||
$(COMPOSER_BIN) install
|
||||
touch $@
|
@ -21,13 +21,14 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"amphp/amp": "^2.0",
|
||||
"amphp/amp": "^2",
|
||||
"amphp/byte-stream": "dev-master as 0.1",
|
||||
"amphp/process": "dev-amp_v2 as 0.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"amphp/phpunit-util": "dev-master",
|
||||
"phpunit/phpunit": "^6.0"
|
||||
"friendsofphp/php-cs-fixer": "^2.3",
|
||||
"phpunit/phpunit": "^6"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"suggest": {
|
||||
|
@ -1,7 +1,8 @@
|
||||
<?php
|
||||
namespace Amp\Parallel\Example;
|
||||
|
||||
use Amp\Parallel\Worker\{ Environment, Task };
|
||||
use Amp\Parallel\Worker\Environment;
|
||||
use Amp\Parallel\Worker\Task;
|
||||
|
||||
class BlockingTask implements Task {
|
||||
/**
|
||||
|
@ -2,8 +2,9 @@
|
||||
<?php
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Threading\Thread;
|
||||
use Amp\{ Loop, Pause };
|
||||
use Amp\Pause;
|
||||
|
||||
Loop::run(function () {
|
||||
$timer = Loop::repeat(1000, function () {
|
||||
@ -11,30 +12,30 @@ Loop::run(function () {
|
||||
$i = $i ? ++$i : 1;
|
||||
print "Demonstrating how alive the parent is for the {$i}th time.\n";
|
||||
});
|
||||
|
||||
|
||||
try {
|
||||
// Create a new child thread that does some blocking stuff.
|
||||
$context = Thread::spawn(function () {
|
||||
printf("\$this: %s\n", get_class($this));
|
||||
|
||||
|
||||
printf("Received the following from parent: %s\n", yield $this->receive());
|
||||
|
||||
|
||||
print "Sleeping for 3 seconds...\n";
|
||||
sleep(3); // Blocking call in thread.
|
||||
|
||||
|
||||
yield $this->send("Data sent from child.");
|
||||
|
||||
|
||||
print "Sleeping for 2 seconds...\n";
|
||||
sleep(2); // Blocking call in thread.
|
||||
|
||||
|
||||
return 42;
|
||||
});
|
||||
|
||||
|
||||
print "Waiting 2 seconds to send start data...\n";
|
||||
yield new Pause(2000);
|
||||
|
||||
|
||||
yield $context->send("Start data");
|
||||
|
||||
|
||||
printf("Received the following from child: %s\n", yield $context->receive());
|
||||
printf("Thread ended with value %d!\n", yield $context->join());
|
||||
} finally {
|
||||
|
@ -2,15 +2,17 @@
|
||||
<?php
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
use Amp\{ Coroutine, Loop };
|
||||
use Amp\Parallel\{ Example\BlockingTask, Worker\DefaultPool };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Example\BlockingTask;
|
||||
use Amp\Parallel\Worker\DefaultPool;
|
||||
|
||||
Loop::run(function() {
|
||||
Loop::run(function () {
|
||||
$timer = Loop::repeat(100, function () {
|
||||
printf(".\n");
|
||||
});
|
||||
Loop::unreference($timer);
|
||||
|
||||
|
||||
$pool = new DefaultPool;
|
||||
$pool->start();
|
||||
|
||||
@ -33,7 +35,7 @@ Loop::run(function() {
|
||||
$result = yield $pool->enqueue(new BlockingTask('file_get_contents', $url));
|
||||
printf("Read from %s: %d bytes\n", $url, strlen($result));
|
||||
};
|
||||
|
||||
|
||||
$coroutines = array_map(function (callable $coroutine): Coroutine {
|
||||
return new Coroutine($coroutine());
|
||||
}, $coroutines);
|
||||
@ -42,4 +44,3 @@ Loop::run(function() {
|
||||
|
||||
return yield $pool->shutdown();
|
||||
});
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
<?php
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
use Amp\Parallel\Worker\DefaultWorkerFactory;
|
||||
use Amp\Parallel\Example\BlockingTask;
|
||||
use Amp\Parallel\Worker\DefaultWorkerFactory;
|
||||
|
||||
Amp\Loop::run(function () {
|
||||
$factory = new DefaultWorkerFactory();
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel;
|
||||
|
||||
class ContextException extends \Exception {}
|
||||
class ContextException extends \Exception {
|
||||
}
|
||||
|
@ -2,10 +2,21 @@
|
||||
|
||||
namespace Amp\Parallel\Forking;
|
||||
|
||||
use Amp\{ Coroutine, Loop, Promise };
|
||||
use Amp\Parallel\{ ContextException, Process, StatusError, Strand, SynchronizationError };
|
||||
use Amp\Parallel\Sync\{ Channel, ChannelException, ChannelledSocket, SerializationException };
|
||||
use Amp\Parallel\Sync\Internal\{ ExitFailure, ExitResult, ExitSuccess };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\ContextException;
|
||||
use Amp\Parallel\Process;
|
||||
use Amp\Parallel\StatusError;
|
||||
use Amp\Parallel\Strand;
|
||||
use Amp\Parallel\Sync\Channel;
|
||||
use Amp\Parallel\Sync\ChannelException;
|
||||
use Amp\Parallel\Sync\ChannelledSocket;
|
||||
use Amp\Parallel\Sync\Internal\ExitFailure;
|
||||
use Amp\Parallel\Sync\Internal\ExitResult;
|
||||
use Amp\Parallel\Sync\Internal\ExitSuccess;
|
||||
use Amp\Parallel\Sync\SerializationException;
|
||||
use Amp\Parallel\SynchronizationError;
|
||||
use Amp\Promise;
|
||||
use function Amp\call;
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@ namespace Amp\Parallel;
|
||||
class PanicError extends \Error {
|
||||
/** @var string Class name of uncaught exception. */
|
||||
private $name;
|
||||
|
||||
|
||||
/** @var string Stack trace of the panic. */
|
||||
private $trace;
|
||||
|
||||
@ -22,7 +22,7 @@ class PanicError extends \Error {
|
||||
$this->name = $name;
|
||||
$this->trace = $trace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the class name of the uncaught exception.
|
||||
*
|
||||
|
@ -2,17 +2,18 @@
|
||||
|
||||
namespace Amp\Parallel\Process;
|
||||
|
||||
use function Amp\call;
|
||||
use Amp\{ Coroutine, Promise };
|
||||
use Amp\Parallel\{
|
||||
ContextException,
|
||||
Process as ProcessContext,
|
||||
StatusError,
|
||||
Strand,
|
||||
SynchronizationError
|
||||
};
|
||||
use Amp\Parallel\Sync\{ ChannelException, ChannelledSocket, Internal\ExitResult };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Parallel\ContextException;
|
||||
use Amp\Parallel\Process as ProcessContext;
|
||||
use Amp\Parallel\StatusError;
|
||||
use Amp\Parallel\Strand;
|
||||
use Amp\Parallel\Sync\ChannelException;
|
||||
use Amp\Parallel\Sync\ChannelledSocket;
|
||||
use Amp\Parallel\Sync\Internal\ExitResult;
|
||||
use Amp\Parallel\SynchronizationError;
|
||||
use Amp\Process\Process;
|
||||
use Amp\Promise;
|
||||
use function Amp\call;
|
||||
|
||||
class ChannelledProcess implements ProcessContext, Strand {
|
||||
/** @var \Amp\Process\Process */
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel;
|
||||
|
||||
class StatusError extends \Error {}
|
||||
class StatusError extends \Error {
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel;
|
||||
|
||||
interface Strand extends Context, Sync\Channel {}
|
||||
interface Strand extends Context, Sync\Channel {
|
||||
}
|
||||
|
@ -2,35 +2,39 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
use Amp\{ Deferred, Failure, Loop, Promise, Success };
|
||||
use Amp\Deferred;
|
||||
use Amp\Failure;
|
||||
use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
class ChannelledSocket implements Channel {
|
||||
const HEADER_LENGTH = 5;
|
||||
|
||||
|
||||
/** @var resource Stream resource. */
|
||||
private $readResource;
|
||||
|
||||
|
||||
/** @var resource Stream resource. */
|
||||
private $writeResource;
|
||||
|
||||
|
||||
/** @var string onReadable loop watcher. */
|
||||
private $readWatcher;
|
||||
|
||||
|
||||
/** @var string onWritable loop watcher. */
|
||||
private $writeWatcher;
|
||||
|
||||
|
||||
/** @var \SplQueue Queue of pending reads. */
|
||||
private $reads;
|
||||
|
||||
|
||||
/** @var \SplQueue Queue of pending writes. */
|
||||
private $writes;
|
||||
|
||||
|
||||
/** @var bool */
|
||||
private $open = true;
|
||||
|
||||
|
||||
/** @var bool */
|
||||
private $autoClose = true;
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $read Readable stream resource.
|
||||
* @param resource $write Writable stream resource.
|
||||
@ -42,28 +46,28 @@ class ChannelledSocket implements Channel {
|
||||
if (!\is_resource($read) || \get_resource_type($read) !== 'stream') {
|
||||
throw new \Error('Invalid resource given to constructor!');
|
||||
}
|
||||
|
||||
|
||||
if (!\is_resource($write) || \get_resource_type($write) !== 'stream') {
|
||||
throw new \Error('Invalid resource given to constructor!');
|
||||
}
|
||||
|
||||
|
||||
$this->readResource = $read;
|
||||
$this->writeResource = $write;
|
||||
$this->autoClose = $autoClose;
|
||||
|
||||
|
||||
\stream_set_blocking($this->readResource, false);
|
||||
\stream_set_read_buffer($this->readResource, 0);
|
||||
\stream_set_write_buffer($this->readResource, 0);
|
||||
|
||||
|
||||
if ($this->readResource !== $this->writeResource) {
|
||||
\stream_set_blocking($this->writeResource, false);
|
||||
\stream_set_read_buffer($this->writeResource, 0);
|
||||
\stream_set_write_buffer($this->writeResource, 0);
|
||||
}
|
||||
|
||||
|
||||
$this->reads = $reads = new \SplQueue;
|
||||
$this->writes = $writes = new \SplQueue;
|
||||
|
||||
|
||||
$errorHandler = static function ($errno, $errstr, $errfile, $errline) {
|
||||
if ($errno & \error_reporting()) {
|
||||
throw new ChannelException(\sprintf(
|
||||
@ -75,56 +79,56 @@ class ChannelledSocket implements Channel {
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$this->readWatcher = Loop::onReadable($this->readResource, static function ($watcher, $stream) use ($reads, $errorHandler) {
|
||||
while (!$reads->isEmpty()) {
|
||||
/** @var \Amp\Deferred $deferred */
|
||||
list($buffer, $length, $deferred) = $reads->shift();
|
||||
|
||||
|
||||
if ($length === 0) {
|
||||
// Error reporting suppressed since fread() produces a warning if the stream unexpectedly closes.
|
||||
$data = @\fread($stream, self::HEADER_LENGTH - \strlen($buffer));
|
||||
|
||||
|
||||
if ($data === false || ($data === '' && (\feof($stream) || !\is_resource($stream)))) {
|
||||
$deferred->fail(new ChannelException("The socket unexpectedly closed"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$buffer .= $data;
|
||||
|
||||
|
||||
if (\strlen($buffer) !== self::HEADER_LENGTH) {
|
||||
// Not enough data available.
|
||||
$reads->unshift([$buffer, 0, $deferred]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$data = \unpack("Cprefix/Llength", $data);
|
||||
|
||||
|
||||
if ($data["prefix"] !== 0) {
|
||||
$deferred->fail(new ChannelException("Invalid header received"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$length = $data["length"];
|
||||
$buffer = '';
|
||||
}
|
||||
|
||||
|
||||
// Error reporting suppressed since fread() produces a warning if the stream unexpectedly closes.
|
||||
$data = @\fread($stream, $length - \strlen($buffer));
|
||||
|
||||
|
||||
if ($data === false || ($data === '' && (\feof($stream) || !\is_resource($stream)))) {
|
||||
$deferred->fail(new ChannelException("The socket unexpectedly closed"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$buffer .= $data;
|
||||
|
||||
|
||||
if (\strlen($buffer) < $length) {
|
||||
// Not enough data available.
|
||||
$reads->unshift([$buffer, $length, $deferred]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
\set_error_handler($errorHandler);
|
||||
|
||||
try {
|
||||
@ -140,10 +144,10 @@ class ChannelledSocket implements Channel {
|
||||
$deferred->fail(new SerializationException("Exception thrown when unserializing data", $exception));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loop::disable($watcher);
|
||||
});
|
||||
|
||||
|
||||
$this->writeWatcher = Loop::onWritable($this->writeResource, static function ($watcher, $stream) use ($writes) {
|
||||
try {
|
||||
while (!$writes->isEmpty()) {
|
||||
@ -167,7 +171,7 @@ class ChannelledSocket implements Channel {
|
||||
$exception = new ChannelException($message);
|
||||
$deferred->fail($exception);
|
||||
while (!$writes->isEmpty()) {
|
||||
list( , , $deferred) = $writes->shift();
|
||||
list(, , $deferred) = $writes->shift();
|
||||
$deferred->fail($exception);
|
||||
}
|
||||
return;
|
||||
@ -188,17 +192,17 @@ class ChannelledSocket implements Channel {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loop::disable($this->readWatcher);
|
||||
Loop::disable($this->writeWatcher);
|
||||
}
|
||||
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->readResource !== null) {
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -206,7 +210,7 @@ class ChannelledSocket implements Channel {
|
||||
if (\is_resource($this->readResource)) {
|
||||
if ($this->autoClose) {
|
||||
@\fclose($this->readResource);
|
||||
|
||||
|
||||
if ($this->readResource !== $this->writeResource) {
|
||||
@\fclose($this->writeResource);
|
||||
}
|
||||
@ -214,23 +218,23 @@ class ChannelledSocket implements Channel {
|
||||
$this->readResource = null;
|
||||
$this->writeResource = null;
|
||||
}
|
||||
|
||||
|
||||
$this->open = false;
|
||||
|
||||
|
||||
if (!$this->reads->isEmpty()) {
|
||||
$exception = new ChannelException("The connection was unexpectedly closed before reading completed");
|
||||
do {
|
||||
/** @var \Amp\Deferred $deferred */
|
||||
list( , , $deferred) = $this->reads->shift();
|
||||
list(, , $deferred) = $this->reads->shift();
|
||||
$deferred->fail($exception);
|
||||
} while (!$this->reads->isEmpty());
|
||||
}
|
||||
|
||||
|
||||
if (!$this->writes->isEmpty()) {
|
||||
$exception = new ChannelException("The connection was unexpectedly writing completed");
|
||||
do {
|
||||
/** @var \Amp\Deferred $deferred */
|
||||
list( , , $deferred) = $this->writes->shift();
|
||||
list(, , $deferred) = $this->writes->shift();
|
||||
$deferred->fail($exception);
|
||||
} while (!$this->writes->isEmpty());
|
||||
}
|
||||
@ -238,7 +242,7 @@ class ChannelledSocket implements Channel {
|
||||
Loop::cancel($this->readWatcher);
|
||||
Loop::cancel($this->writeWatcher);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -246,13 +250,13 @@ class ChannelledSocket implements Channel {
|
||||
if (!$this->open) {
|
||||
return new Failure(new ChannelException("The channel is has been closed"));
|
||||
}
|
||||
|
||||
|
||||
$deferred = new Deferred;
|
||||
$this->reads->push(["", 0, $deferred]);
|
||||
Loop::enable($this->readWatcher);
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @param bool $end
|
||||
@ -272,7 +276,7 @@ class ChannelledSocket implements Channel {
|
||||
"The given data cannot be sent because it is not serializable.", $exception
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$data = \pack("CL", 0, \strlen($data)) . $data;
|
||||
$length = \strlen($data);
|
||||
$written = 0;
|
||||
@ -280,7 +284,7 @@ class ChannelledSocket implements Channel {
|
||||
if ($this->writes->isEmpty()) {
|
||||
// Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
|
||||
$written = @\fwrite($this->writeResource, $data);
|
||||
|
||||
|
||||
if ($written === false) {
|
||||
$message = "Failed to write to stream";
|
||||
if ($error = \error_get_last()) {
|
||||
@ -288,11 +292,11 @@ class ChannelledSocket implements Channel {
|
||||
}
|
||||
return new Failure(new ChannelException($message));
|
||||
}
|
||||
|
||||
|
||||
if ($length <= $written) {
|
||||
return new Success($written);
|
||||
}
|
||||
|
||||
|
||||
$data = \substr($data, $written);
|
||||
}
|
||||
|
||||
@ -301,4 +305,4 @@ class ChannelledSocket implements Channel {
|
||||
Loop::enable($this->writeWatcher);
|
||||
return $deferred->promise();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
use Amp\{ Coroutine, Promise };
|
||||
use Amp\ByteStream\{ InputStream, OutputStream, Parser, StreamException };
|
||||
use Amp\ByteStream\InputStream;
|
||||
use Amp\ByteStream\OutputStream;
|
||||
use Amp\ByteStream\Parser;
|
||||
use Amp\ByteStream\StreamException;
|
||||
use Amp\Coroutine;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* An asynchronous channel for sending data between threads and processes.
|
||||
|
@ -4,7 +4,6 @@ namespace Amp\Parallel\Sync;
|
||||
|
||||
use Amp\Coroutine;
|
||||
use Amp\Delayed;
|
||||
use Amp\Pause;
|
||||
use Amp\Parallel\MutexException;
|
||||
use Amp\Promise;
|
||||
|
||||
|
@ -39,4 +39,4 @@ class ExitFailure implements ExitResult {
|
||||
$this->trace
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,4 +16,4 @@ class ExitSuccess implements ExitResult {
|
||||
public function getResult() {
|
||||
return $this->result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
class LockAlreadyReleasedError extends \Error {}
|
||||
class LockAlreadyReleasedError extends \Error {
|
||||
}
|
||||
|
@ -11,8 +11,7 @@ use Amp\Promise;
|
||||
* are atomic. Implementations do not have to guarantee that acquiring a lock
|
||||
* is first-come, first serve.
|
||||
*/
|
||||
interface Mutex
|
||||
{
|
||||
interface Mutex {
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
class MutexException extends \Exception {}
|
||||
class MutexException extends \Exception {
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class PosixSemaphore implements Semaphore, \Serializable {
|
||||
public function acquire(): Promise {
|
||||
return new Coroutine($this->doAcquire());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
class SemaphoreException extends \Exception {}
|
||||
class SemaphoreException extends \Exception {
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
class SerializationException extends ChannelException {}
|
||||
class SerializationException extends ChannelException {
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
class SharedMemoryException extends \Exception {}
|
||||
class SharedMemoryException extends \Exception {
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Sync;
|
||||
|
||||
use Amp\{ Coroutine, Promise };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* A container object for sharing a value across contexts.
|
||||
@ -164,7 +165,7 @@ class SharedMemoryParcel implements Parcel, \Serializable {
|
||||
public function synchronized(callable $callback): Promise {
|
||||
return new Coroutine($this->doSynchronized($callback));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
@ -175,28 +176,28 @@ class SharedMemoryParcel implements Parcel, \Serializable {
|
||||
private function doSynchronized(callable $callback): \Generator {
|
||||
/** @var \Amp\Parallel\Sync\Lock $lock */
|
||||
$lock = yield $this->semaphore->acquire();
|
||||
|
||||
|
||||
try {
|
||||
$value = $this->unwrap();
|
||||
$result = $callback($value);
|
||||
|
||||
|
||||
if ($result instanceof \Generator) {
|
||||
$result = new Coroutine($result);
|
||||
}
|
||||
|
||||
|
||||
if ($result instanceof Promise) {
|
||||
$result = yield $result;
|
||||
}
|
||||
|
||||
|
||||
$this->wrap(null === $result ? $value : $result);
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Frees the shared object from memory.
|
||||
*
|
||||
|
@ -2,4 +2,5 @@
|
||||
|
||||
namespace Amp\Parallel;
|
||||
|
||||
class SynchronizationError extends \Error {}
|
||||
class SynchronizationError extends \Error {
|
||||
}
|
||||
|
@ -15,14 +15,14 @@ class Mutex extends \Threaded {
|
||||
|
||||
/** @var bool */
|
||||
private $lock = true;
|
||||
|
||||
|
||||
/**
|
||||
* @return \Amp\Promise
|
||||
*/
|
||||
public function acquire(): Promise {
|
||||
return new Coroutine($this->doAcquire());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to acquire the lock and sleeps for a time if the lock could not be acquired.
|
||||
*
|
||||
|
@ -42,7 +42,7 @@ class Semaphore extends \Threaded {
|
||||
public function acquire(): Promise {
|
||||
return new Coroutine($this->doAcquire());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uses a double locking mechanism to acquire a lock without blocking. A
|
||||
* synchronous mutex is used to make sure that the semaphore is queried one
|
||||
|
@ -2,15 +2,15 @@
|
||||
|
||||
namespace Amp\Parallel\Threading\Internal;
|
||||
|
||||
use Amp\{ Coroutine, Loop, Promise };
|
||||
use Amp\Parallel\Sync\{
|
||||
Channel,
|
||||
ChannelException,
|
||||
ChannelledSocket,
|
||||
Internal\ExitFailure,
|
||||
Internal\ExitSuccess,
|
||||
SerializationException
|
||||
};
|
||||
use Amp\Coroutine;
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Sync\Channel;
|
||||
use Amp\Parallel\Sync\ChannelException;
|
||||
use Amp\Parallel\Sync\ChannelledSocket;
|
||||
use Amp\Parallel\Sync\Internal\ExitFailure;
|
||||
use Amp\Parallel\Sync\Internal\ExitSuccess;
|
||||
use Amp\Parallel\Sync\SerializationException;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* An internal thread that executes a given function concurrently.
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Threading;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Parallel\Sync\Mutex as SyncMutex;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* A thread-safe, asynchronous mutex using the pthreads locking mechanism.
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
namespace Amp\Parallel\Threading;
|
||||
|
||||
use Amp\{ Coroutine, Promise };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Parallel\Sync\Parcel as SyncParcel;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* A thread-safe container that shares a value between multiple threads.
|
||||
@ -52,7 +53,7 @@ class Parcel implements SyncParcel {
|
||||
public function synchronized(callable $callback): Promise {
|
||||
return new Coroutine($this->doSynchronized($callback));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
@ -70,15 +71,15 @@ class Parcel implements SyncParcel {
|
||||
try {
|
||||
$value = $this->unwrap();
|
||||
$result = $callback($value);
|
||||
|
||||
|
||||
if ($result instanceof \Generator) {
|
||||
$result = new Coroutine($result);
|
||||
}
|
||||
|
||||
|
||||
if ($result instanceof Promise) {
|
||||
$result = yield $result;
|
||||
}
|
||||
|
||||
|
||||
$this->wrap(null === $result ? $value : $result);
|
||||
} finally {
|
||||
$lock->release();
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Threading;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Parallel\Sync\Semaphore as SyncSemaphore;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* An asynchronous semaphore based on pthreads' synchronization methods.
|
||||
|
@ -2,10 +2,17 @@
|
||||
|
||||
namespace Amp\Parallel\Threading;
|
||||
|
||||
use Amp\Coroutine;
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\ContextException;
|
||||
use Amp\Parallel\StatusError;
|
||||
use Amp\Parallel\Strand;
|
||||
use Amp\Parallel\Sync\ChannelException;
|
||||
use Amp\Parallel\Sync\ChannelledSocket;
|
||||
use Amp\Parallel\Sync\Internal\ExitResult;
|
||||
use Amp\Parallel\SynchronizationError;
|
||||
use Amp\Promise;
|
||||
use function Amp\call;
|
||||
use Amp\{ Coroutine, Loop, Promise };
|
||||
use Amp\Parallel\{ ContextException, StatusError, SynchronizationError, Strand };
|
||||
use Amp\Parallel\Sync\{ ChannelException, ChannelledSocket, Internal\ExitResult };
|
||||
|
||||
/**
|
||||
* Implements an execution context using native multi-threading.
|
||||
|
@ -2,9 +2,14 @@
|
||||
|
||||
namespace Amp\Parallel\Worker;
|
||||
|
||||
use Amp\{ Coroutine, Deferred, Promise };
|
||||
use Amp\Parallel\{ StatusError, Strand } ;
|
||||
use Amp\Parallel\Worker\Internal\{ Job, TaskResult };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Deferred;
|
||||
use Amp\Parallel\StatusError;
|
||||
use Amp\Parallel\Strand;
|
||||
use Amp\Parallel\Worker\Internal\Job;
|
||||
|
||||
use Amp\Parallel\Worker\Internal\TaskResult;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* Base class for most common types of task workers.
|
||||
@ -15,10 +20,10 @@ abstract class AbstractWorker implements Worker {
|
||||
|
||||
/** @var bool */
|
||||
private $shutdown = false;
|
||||
|
||||
|
||||
/** @var \Amp\Deferred[] */
|
||||
private $jobQueue = [];
|
||||
|
||||
|
||||
/** @var callable */
|
||||
private $when;
|
||||
|
||||
@ -27,32 +32,32 @@ abstract class AbstractWorker implements Worker {
|
||||
*/
|
||||
public function __construct(Strand $strand) {
|
||||
$this->context = $strand;
|
||||
|
||||
|
||||
$this->when = function ($exception, $data) {
|
||||
if ($exception) {
|
||||
$this->kill();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!$data instanceof TaskResult) {
|
||||
$this->kill();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$id = $data->getId();
|
||||
|
||||
|
||||
if (!isset($this->jobQueue[$id])) {
|
||||
$this->kill();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$deferred = $this->jobQueue[$id];
|
||||
unset($this->jobQueue[$id]);
|
||||
|
||||
|
||||
if (!empty($this->jobQueue)) {
|
||||
$this->context->receive()->onResolve($this->when);
|
||||
}
|
||||
|
||||
|
||||
$deferred->resolve($data->promise());
|
||||
};
|
||||
}
|
||||
@ -85,11 +90,11 @@ abstract class AbstractWorker implements Worker {
|
||||
if (!$this->context->isRunning()) {
|
||||
throw new StatusError('The worker has not been started.');
|
||||
}
|
||||
|
||||
|
||||
if ($this->shutdown) {
|
||||
throw new StatusError('The worker has been shut down.');
|
||||
}
|
||||
|
||||
|
||||
return new Coroutine($this->doEnqueue($task));
|
||||
}
|
||||
|
||||
@ -108,7 +113,7 @@ abstract class AbstractWorker implements Worker {
|
||||
if (empty($this->jobQueue)) {
|
||||
$this->context->receive()->onResolve($this->when);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$job = new Job($task);
|
||||
$this->jobQueue[$job->getId()] = $deferred = new Deferred;
|
||||
@ -117,7 +122,7 @@ abstract class AbstractWorker implements Worker {
|
||||
$this->kill();
|
||||
throw new WorkerException('Sending the task to the worker failed.', $exception);
|
||||
}
|
||||
|
||||
|
||||
return yield $deferred->promise();
|
||||
}
|
||||
|
||||
@ -128,7 +133,7 @@ abstract class AbstractWorker implements Worker {
|
||||
if (!$this->context->isRunning() || $this->shutdown) {
|
||||
throw new StatusError('The worker is not running.');
|
||||
}
|
||||
|
||||
|
||||
return new Coroutine($this->doShutdown());
|
||||
}
|
||||
|
||||
@ -161,11 +166,11 @@ abstract class AbstractWorker implements Worker {
|
||||
private function cancelPending() {
|
||||
if (!empty($this->jobQueue)) {
|
||||
$exception = new WorkerException('Worker was shut down.');
|
||||
|
||||
|
||||
foreach ($this->jobQueue as $job) {
|
||||
$job->fail($exception);
|
||||
}
|
||||
|
||||
|
||||
$this->jobQueue = [];
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class BasicEnvironment implements Environment {
|
||||
Loop::disable($this->timer);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loop::disable($this->timer);
|
||||
Loop::unreference($this->timer);
|
||||
}
|
||||
@ -70,7 +70,7 @@ class BasicEnvironment implements Environment {
|
||||
|
||||
return isset($this->data[$key]) ? $this->data[$key] : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value Using null for the value deletes the key.
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
namespace Amp\Parallel\Worker;
|
||||
|
||||
use Amp\{ CallableMaker, Coroutine, Promise };
|
||||
use Amp\CallableMaker;
|
||||
use Amp\Coroutine;
|
||||
use Amp\Parallel\StatusError;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* Provides a pool of workers that can be used to execute multiple tasks asynchronously.
|
||||
@ -14,7 +16,7 @@ use Amp\Parallel\StatusError;
|
||||
*/
|
||||
class DefaultPool implements Pool {
|
||||
use CallableMaker;
|
||||
|
||||
|
||||
/** @var bool Indicates if the pool is currently running. */
|
||||
private $running = false;
|
||||
|
||||
@ -156,7 +158,7 @@ class DefaultPool implements Pool {
|
||||
public function enqueue(Task $task): Promise {
|
||||
return new Coroutine($this->doEnqueue($this->pull(), $task));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
@ -173,7 +175,7 @@ class DefaultPool implements Pool {
|
||||
} finally {
|
||||
$this->push($worker);
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -190,7 +192,7 @@ class DefaultPool implements Pool {
|
||||
if (!$this->isRunning()) {
|
||||
throw new StatusError('The pool is not running.');
|
||||
}
|
||||
|
||||
|
||||
return new Coroutine($this->doShutdown());
|
||||
}
|
||||
|
||||
@ -247,7 +249,7 @@ class DefaultPool implements Pool {
|
||||
public function get(): Worker {
|
||||
return new Internal\PooledWorker($this->pull(), $this->push);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pulls a worker from the pool. The worker should be put back into the pool with push() to be marked as idle.
|
||||
*
|
||||
@ -282,7 +284,7 @@ class DefaultPool implements Pool {
|
||||
|
||||
$this->busyQueue->push($worker);
|
||||
$this->workers[$worker] += 1;
|
||||
|
||||
|
||||
return $worker;
|
||||
}
|
||||
|
||||
|
@ -7,19 +7,19 @@ use Amp\Parallel\Worker\Task;
|
||||
class Job {
|
||||
/** @var string */
|
||||
private $id;
|
||||
|
||||
|
||||
/** @var \Amp\Parallel\Worker\Task */
|
||||
private $task;
|
||||
|
||||
|
||||
public function __construct(Task $task) {
|
||||
$this->task = $task;
|
||||
$this->id = \spl_object_hash($this->task);
|
||||
}
|
||||
|
||||
|
||||
public function getId(): string {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
public function getTask(): Task {
|
||||
return $this->task;
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Worker\Internal;
|
||||
|
||||
use Amp\Parallel\Worker\{ Task, Worker };
|
||||
use Amp\Parallel\Worker\Task;
|
||||
use Amp\Parallel\Worker\Worker;
|
||||
use Amp\Promise;
|
||||
|
||||
class PooledWorker implements Worker {
|
||||
@ -69,4 +70,4 @@ class PooledWorker implements Worker {
|
||||
public function kill() {
|
||||
$this->worker->kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class TaskFailure extends TaskResult {
|
||||
$this->code = $exception->getCode();
|
||||
$this->trace = $exception->getTraceAsString();
|
||||
}
|
||||
|
||||
|
||||
public function promise(): Promise {
|
||||
switch ($this->parent) {
|
||||
case self::PARENT_ERROR:
|
||||
@ -57,4 +57,4 @@ class TaskFailure extends TaskResult {
|
||||
|
||||
return new Failure($exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,23 +7,23 @@ use Amp\Promise;
|
||||
abstract class TaskResult {
|
||||
/** @var string Task identifier. */
|
||||
private $id;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id Task identifier.
|
||||
*/
|
||||
public function __construct(string $id) {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string Task identifier.
|
||||
*/
|
||||
public function getId(): string {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Amp\Promise<mixed> Resolved with the task result or failure reason.
|
||||
*/
|
||||
abstract public function promise(): Promise;
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,12 @@
|
||||
|
||||
namespace Amp\Parallel\Worker\Internal;
|
||||
|
||||
use Amp\{ Coroutine, Failure, Success };
|
||||
use Amp\Parallel\{ Sync\Channel, Worker\Environment };
|
||||
use Amp\Coroutine;
|
||||
use Amp\Failure;
|
||||
use Amp\Parallel\Sync\Channel;
|
||||
use Amp\Parallel\Worker\Environment;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
class TaskRunner {
|
||||
/** @var \Amp\Parallel\Sync\Channel */
|
||||
@ -17,7 +20,7 @@ class TaskRunner {
|
||||
$this->channel = $channel;
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs the task runner, receiving tasks from the parent and sending the result of those tasks.
|
||||
*
|
||||
@ -26,7 +29,7 @@ class TaskRunner {
|
||||
public function run(): Promise {
|
||||
return new Coroutine($this->execute());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @coroutine
|
||||
*
|
||||
@ -37,28 +40,28 @@ class TaskRunner {
|
||||
|
||||
while ($job instanceof Job) {
|
||||
$task = $job->getTask();
|
||||
|
||||
|
||||
try {
|
||||
$result = $task->run($this->environment);
|
||||
|
||||
|
||||
if ($result instanceof \Generator) {
|
||||
$result = new Coroutine($result);
|
||||
}
|
||||
|
||||
|
||||
if (!$result instanceof Promise) {
|
||||
$result = new Success($result);
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$result = new Failure($exception);
|
||||
}
|
||||
|
||||
|
||||
$result->onResolve(function ($exception, $value) use ($job) {
|
||||
if ($exception) {
|
||||
$result = new TaskFailure($job->getId(), $exception);
|
||||
} else {
|
||||
$result = new TaskSuccess($job->getId(), $value);
|
||||
}
|
||||
|
||||
|
||||
$this->channel->send($result);
|
||||
});
|
||||
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
namespace Amp\Parallel\Worker\Internal;
|
||||
|
||||
use Amp\Success;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
class TaskSuccess extends TaskResult {
|
||||
/** @var mixed Result of task. */
|
||||
private $result;
|
||||
|
||||
|
||||
public function __construct(string $id, $result) {
|
||||
parent::__construct($id);
|
||||
$this->result = $result;
|
||||
}
|
||||
|
||||
|
||||
public function promise(): Promise {
|
||||
return new Success($this->result);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class TaskError extends \Error {
|
||||
$this->name = $name;
|
||||
$this->trace = $trace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the class name of the error thrown from the task.
|
||||
*
|
||||
@ -29,7 +29,7 @@ class TaskError extends \Error {
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the stack trace at the point the error was thrown in the task.
|
||||
*
|
||||
|
@ -20,7 +20,7 @@ class TaskException extends \Exception {
|
||||
$this->name = $name;
|
||||
$this->trace = $trace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the class name of the exception thrown from the task.
|
||||
*
|
||||
@ -29,7 +29,7 @@ class TaskException extends \Exception {
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the stack trace at the point the exception was thrown in the task.
|
||||
*
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Amp\Parallel\Worker;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Parallel\Threading\Thread;
|
||||
use Amp\Parallel\Worker\Internal\TaskRunner;
|
||||
use Amp\Promise;
|
||||
|
||||
/**
|
||||
* A worker thread that executes task objects.
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Worker;
|
||||
|
||||
use Amp\{ Loop, Promise };
|
||||
use Amp\Loop;
|
||||
use Amp\Promise;
|
||||
|
||||
const LOOP_POOL_IDENTIFIER = Pool::class;
|
||||
const LOOP_FACTORY_IDENTIFIER = WorkerFactory::class;
|
||||
|
@ -113,7 +113,6 @@ abstract class AbstractContextTest extends TestCase {
|
||||
$context->start();
|
||||
yield $context->join();
|
||||
});
|
||||
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Forking;
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Forking\Fork;
|
||||
use Amp\Parallel\Test\AbstractContextTest;
|
||||
use Amp\Loop;
|
||||
|
||||
/**
|
||||
* @group forking
|
||||
|
@ -96,13 +96,13 @@ abstract class AbstractSemaphoreTest extends TestCase {
|
||||
$callback = function () {
|
||||
$awaitable1 = $this->semaphore->acquire();
|
||||
$awaitable2 = $this->semaphore->acquire();
|
||||
|
||||
|
||||
yield new Delayed(500);
|
||||
|
||||
|
||||
(yield $awaitable1)->release();
|
||||
|
||||
|
||||
yield new Delayed(500);
|
||||
|
||||
|
||||
(yield $awaitable2)->release();
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ class ChannelledSocketTest extends TestCase {
|
||||
}
|
||||
return $sockets;
|
||||
}
|
||||
|
||||
|
||||
public function testSendReceive() {
|
||||
Loop::run(function () {
|
||||
list($left, $right) = $this->createSockets();
|
||||
@ -54,7 +54,6 @@ class ChannelledSocketTest extends TestCase {
|
||||
$data = yield $b->receive();
|
||||
$this->assertSame($message, $data);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,7 +69,6 @@ class ChannelledSocketTest extends TestCase {
|
||||
fwrite($left, pack('L', 10) . '1234567890');
|
||||
$data = yield $b->receive();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,7 +85,6 @@ class ChannelledSocketTest extends TestCase {
|
||||
yield $a->send(function () {});
|
||||
$data = yield $b->receive();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +99,6 @@ class ChannelledSocketTest extends TestCase {
|
||||
|
||||
yield $a->send('hello');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +113,5 @@ class ChannelledSocketTest extends TestCase {
|
||||
|
||||
$data = yield $a->receive();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
namespace Amp\Parallel\Test\Sync;
|
||||
|
||||
use Amp\ByteStream\InputStream;
|
||||
use Amp\ByteStream\StreamException;
|
||||
use Amp\ByteStream\OutputStream;
|
||||
use Amp\ByteStream\StreamException;
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Sync\ChannelledStream;
|
||||
use Amp\PHPUnit\TestCase;
|
||||
@ -73,7 +73,6 @@ class ChannelledStreamTest extends TestCase {
|
||||
$data = yield $b->receive();
|
||||
$this->assertSame($message, $data);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +89,6 @@ class ChannelledStreamTest extends TestCase {
|
||||
yield $mock->write(pack('L', 10) . '1234567890');
|
||||
$data = yield $b->receive();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +105,6 @@ class ChannelledStreamTest extends TestCase {
|
||||
yield $a->send(function () {});
|
||||
$data = yield $b->receive();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +126,6 @@ class ChannelledStreamTest extends TestCase {
|
||||
|
||||
yield $a->send('hello');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,6 +143,5 @@ class ChannelledStreamTest extends TestCase {
|
||||
|
||||
$data = yield $a->receive();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ class FileMutexTest extends TestCase {
|
||||
$lock->release();
|
||||
$this->assertTrue($lock->isReleased());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function testAcquireMultiple() {
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Sync;
|
||||
|
||||
use Amp\Parallel\Forking\Fork;
|
||||
use Amp\Parallel\Sync\{ PosixSemaphore, Semaphore };
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Forking\Fork;
|
||||
use Amp\Parallel\Sync\PosixSemaphore;
|
||||
use Amp\Parallel\Sync\Semaphore;
|
||||
|
||||
/**
|
||||
* @group posix
|
||||
@ -40,7 +41,6 @@ class PosixSemaphoreTest extends AbstractSemaphoreTest {
|
||||
|
||||
$clone->free();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function testFree() {
|
||||
|
@ -18,7 +18,6 @@ class MutexTest extends TestCase {
|
||||
$lock->release();
|
||||
$this->assertTrue($lock->isReleased());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function testAcquireMultiple() {
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Threading;
|
||||
|
||||
use Amp\Parallel\Threading\Parcel;
|
||||
use Amp\Parallel\Test\Sync\AbstractParcelTest;
|
||||
use Amp\Parallel\Threading\Parcel;
|
||||
|
||||
/**
|
||||
* @requires extension pthreads
|
||||
|
@ -4,8 +4,9 @@ namespace Amp\Parallel\Test\Threading;
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Sync\Semaphore as SyncSemaphore;
|
||||
use Amp\Parallel\Threading\{Semaphore, Thread};
|
||||
use Amp\Parallel\Test\Sync\AbstractSemaphoreTest;
|
||||
use Amp\Parallel\Threading\Semaphore;
|
||||
use Amp\Parallel\Threading\Thread;
|
||||
|
||||
/**
|
||||
* @group threading
|
||||
|
@ -3,8 +3,8 @@
|
||||
namespace Amp\Parallel\Test\Threading;
|
||||
|
||||
use Amp\Loop;
|
||||
use Amp\Parallel\Threading\Thread;
|
||||
use Amp\Parallel\Test\AbstractContextTest;
|
||||
use Amp\Parallel\Threading\Thread;
|
||||
|
||||
/**
|
||||
* @group threading
|
||||
@ -25,6 +25,5 @@ class ThreadTest extends AbstractContextTest {
|
||||
|
||||
return yield $thread->join();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ abstract class AbstractWorkerTest extends TestCase {
|
||||
Loop::run(function () {
|
||||
$worker = $this->createWorker();
|
||||
$worker->start();
|
||||
|
||||
|
||||
$values = yield \Amp\Promise\all([
|
||||
$worker->enqueue(new TestTask(42)),
|
||||
$worker->enqueue(new TestTask(56)),
|
||||
|
@ -3,10 +3,13 @@
|
||||
namespace Amp\Parallel\Test\Worker;
|
||||
|
||||
use Amp\Parallel\Worker;
|
||||
use Amp\Parallel\Worker\{ Environment, Pool, Task, WorkerFactory };
|
||||
use Amp\Parallel\Worker\Environment;
|
||||
use Amp\Parallel\Worker\Pool;
|
||||
use Amp\Parallel\Worker\Task;
|
||||
use Amp\Parallel\Worker\WorkerFactory;
|
||||
use Amp\PHPUnit\TestCase;
|
||||
use Amp\Success;
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
|
||||
class FunctionsTest extends TestCase {
|
||||
public function testPool() {
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Worker;
|
||||
|
||||
use Amp\Parallel\Worker\{ DefaultPool, WorkerFactory, WorkerProcess };
|
||||
use Amp\Parallel\Worker\DefaultPool;
|
||||
use Amp\Parallel\Worker\WorkerFactory;
|
||||
use Amp\Parallel\Worker\WorkerProcess;
|
||||
|
||||
/**
|
||||
* @group process
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Worker;
|
||||
|
||||
use Amp\Parallel\Worker\{ Environment, Task };
|
||||
use Amp\Parallel\Worker\Environment;
|
||||
use Amp\Parallel\Worker\Task;
|
||||
|
||||
class TestTask implements Task {
|
||||
private $returnValue;
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace Amp\Parallel\Test\Worker;
|
||||
|
||||
use Amp\Parallel\Worker\{ DefaultPool, WorkerFactory, WorkerThread };
|
||||
use Amp\Parallel\Worker\DefaultPool;
|
||||
use Amp\Parallel\Worker\WorkerFactory;
|
||||
use Amp\Parallel\Worker\WorkerThread;
|
||||
|
||||
/**
|
||||
* @group threading
|
||||
|
Loading…
Reference in New Issue
Block a user