2019-08-02 22:09:38 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Amp;
|
|
|
|
|
2021-10-15 00:50:40 +02:00
|
|
|
use Revolt\EventLoop;
|
2021-03-26 22:34:32 +01:00
|
|
|
|
2021-12-02 22:24:56 +01:00
|
|
|
final class CompositeCancellation implements Cancellation
|
2019-08-02 22:09:38 +02:00
|
|
|
{
|
2021-12-02 22:24:56 +01:00
|
|
|
/** @var array<int, array{Cancellation, string}> */
|
|
|
|
private array $cancellations = [];
|
2019-08-02 22:09:38 +02:00
|
|
|
|
2020-10-02 20:55:46 +02:00
|
|
|
private string $nextId = "a";
|
2020-03-28 12:23:46 +01:00
|
|
|
|
2021-12-02 22:24:56 +01:00
|
|
|
/** @var \Closure(CancelledException)[] */
|
2020-10-02 20:55:46 +02:00
|
|
|
private array $callbacks = [];
|
2020-03-28 12:23:46 +01:00
|
|
|
|
2021-09-04 01:15:31 +02:00
|
|
|
private ?CancelledException $exception = null;
|
2019-08-02 22:09:38 +02:00
|
|
|
|
2021-12-02 22:24:56 +01:00
|
|
|
public function __construct(Cancellation ...$cancellations)
|
2019-08-02 22:09:38 +02:00
|
|
|
{
|
2021-12-02 22:24:56 +01:00
|
|
|
foreach ($cancellations as $cancellation) {
|
|
|
|
$id = $cancellation->subscribe(function (CancelledException $exception): void {
|
2019-08-02 22:09:38 +02:00
|
|
|
$this->exception = $exception;
|
|
|
|
|
2021-12-02 22:24:56 +01:00
|
|
|
foreach ($this->callbacks as $callback) {
|
2021-10-15 00:50:40 +02:00
|
|
|
EventLoop::queue($callback, $exception);
|
2019-08-02 22:09:38 +02:00
|
|
|
}
|
2021-12-02 22:24:56 +01:00
|
|
|
|
|
|
|
$this->callbacks = [];
|
2019-08-02 22:09:38 +02:00
|
|
|
});
|
|
|
|
|
2021-12-02 22:24:56 +01:00
|
|
|
$this->cancellations[] = [$cancellation, $id];
|
2019-08-02 22:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __destruct()
|
|
|
|
{
|
2021-12-02 22:40:18 +01:00
|
|
|
foreach ($this->cancellations as [$cancellation, $id]) {
|
|
|
|
/** @var Cancellation $cancellation */
|
|
|
|
$cancellation->unsubscribe($id);
|
2019-08-02 22:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 18:40:51 +01:00
|
|
|
public function subscribe(\Closure $callback): string
|
2019-08-02 22:09:38 +02:00
|
|
|
{
|
|
|
|
$id = $this->nextId++;
|
|
|
|
|
2021-09-04 01:15:31 +02:00
|
|
|
if ($this->exception) {
|
2021-10-15 00:50:40 +02:00
|
|
|
EventLoop::queue($callback, $this->exception);
|
2019-08-02 22:09:38 +02:00
|
|
|
} else {
|
|
|
|
$this->callbacks[$id] = $callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
2020-09-25 05:17:13 +02:00
|
|
|
public function unsubscribe(string $id): void
|
2019-08-02 22:09:38 +02:00
|
|
|
{
|
|
|
|
unset($this->callbacks[$id]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
|
|
|
public function isRequested(): bool
|
|
|
|
{
|
2021-12-02 22:40:18 +01:00
|
|
|
foreach ($this->cancellations as [$cancellation]) {
|
|
|
|
if ($cancellation->isRequested()) {
|
2019-08-02 22:09:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritdoc */
|
2020-09-25 05:17:13 +02:00
|
|
|
public function throwIfRequested(): void
|
2019-08-02 22:09:38 +02:00
|
|
|
{
|
2021-12-02 22:40:18 +01:00
|
|
|
foreach ($this->cancellations as [$cancellation]) {
|
|
|
|
$cancellation->throwIfRequested();
|
2019-08-02 22:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|