mirror of
https://github.com/danog/amp.git
synced 2024-11-26 20:15:00 +01:00
Add TimeoutCancellationToken
This commit is contained in:
parent
5d9cf8a11d
commit
5f3e21a4a4
@ -117,13 +117,16 @@ final class CancellationTokenSource {
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
public function cancel() {
|
||||
/**
|
||||
* @param \Throwable|null $previous Exception to be used as the previous exception to CancelledException.
|
||||
*/
|
||||
public function cancel(\Throwable $previous = null) {
|
||||
if ($this->onCancel === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$onCancel = $this->onCancel;
|
||||
$this->onCancel = null;
|
||||
$onCancel(new CancelledException);
|
||||
$onCancel(new CancelledException($previous));
|
||||
}
|
||||
}
|
||||
|
@ -9,4 +9,7 @@ namespace Amp;
|
||||
* @see CancellationTokenSource
|
||||
*/
|
||||
class CancelledException extends \Exception {
|
||||
public function __construct(\Throwable $previous = null) {
|
||||
parent::__construct("The operation was cancelled", 0, $previous);
|
||||
}
|
||||
}
|
||||
|
62
lib/TimeoutCancellationToken.php
Normal file
62
lib/TimeoutCancellationToken.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Amp;
|
||||
|
||||
/**
|
||||
* A TimeoutCancellationToken automatically requests cancellation after the timeout has elapsed.
|
||||
*/
|
||||
final class TimeoutCancellationToken implements CancellationToken {
|
||||
/** @var string */
|
||||
private $watcher;
|
||||
|
||||
/** @var \Amp\CancellationToken */
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* @param int $timeout Milliseconds until cancellation is requested.
|
||||
*/
|
||||
public function __construct(int $timeout) {
|
||||
$source = new CancellationTokenSource;
|
||||
$this->token = $source->getToken();
|
||||
|
||||
$this->watcher = Loop::delay($timeout, static function () use ($source) {
|
||||
$source->cancel(new TimeoutException);
|
||||
});
|
||||
Loop::unreference($this->watcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the delay watcher.
|
||||
*/
|
||||
public function __destruct() {
|
||||
Loop::cancel($this->watcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subscribe(callable $callback): string {
|
||||
return $this->token->subscribe($callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unsubscribe(string $id) {
|
||||
$this->token->unsubscribe($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRequested(): bool {
|
||||
return $this->token->isRequested();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function throwIfRequested() {
|
||||
$this->token->throwIfRequested();
|
||||
}
|
||||
}
|
37
test/TimeoutCancellationTokenTest.php
Normal file
37
test/TimeoutCancellationTokenTest.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Amp\Test;
|
||||
|
||||
use Amp\CancelledException;
|
||||
use Amp\Delayed;
|
||||
use Amp\Loop;
|
||||
use Amp\PHPUnit\TestCase;
|
||||
use Amp\TimeoutCancellationToken;
|
||||
use Amp\TimeoutException;
|
||||
|
||||
class TimeoutCancellationTokenTest extends TestCase {
|
||||
public function testTimeout() {
|
||||
Loop::run(function () {
|
||||
$token = new TimeoutCancellationToken(10);
|
||||
|
||||
$this->assertFalse($token->isRequested());
|
||||
yield new Delayed(20);
|
||||
$this->assertTrue($token->isRequested());
|
||||
|
||||
try {
|
||||
$token->throwIfRequested();
|
||||
} catch (CancelledException $exception) {
|
||||
$this->assertInstanceOf(TimeoutException::class, $exception->getPrevious());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function testWatcherCancellation() {
|
||||
Loop::run(function () {
|
||||
$token = new TimeoutCancellationToken(1);
|
||||
$this->assertSame(1, Loop::getInfo()["delay"]["enabled"]);
|
||||
unset($token);
|
||||
$this->assertSame(0, Loop::getInfo()["delay"]["enabled"]);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user