CancellationQueue.php 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. <?php
  2. namespace React\Promise\Internal;
  3. /**
  4. * @internal
  5. */
  6. final class CancellationQueue
  7. {
  8. /** @var bool */
  9. private $started = false;
  10. /** @var object[] */
  11. private $queue = [];
  12. public function __invoke(): void
  13. {
  14. if ($this->started) {
  15. return;
  16. }
  17. $this->started = true;
  18. $this->drain();
  19. }
  20. /**
  21. * @param mixed $cancellable
  22. */
  23. public function enqueue($cancellable): void
  24. {
  25. if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
  26. return;
  27. }
  28. $length = \array_push($this->queue, $cancellable);
  29. if ($this->started && 1 === $length) {
  30. $this->drain();
  31. }
  32. }
  33. private function drain(): void
  34. {
  35. for ($i = \key($this->queue); isset($this->queue[$i]); $i++) {
  36. $cancellable = $this->queue[$i];
  37. assert(\method_exists($cancellable, 'cancel'));
  38. $exception = null;
  39. try {
  40. $cancellable->cancel();
  41. } catch (\Throwable $exception) {
  42. }
  43. unset($this->queue[$i]);
  44. if ($exception) {
  45. throw $exception;
  46. }
  47. }
  48. $this->queue = [];
  49. }
  50. }