Lines 80.00% 20 / 25
Methods 83.33% 5 / 6
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 runSettled 100.00% 9 / 9 100.00% 1 / 1 3
 rethrowFailures 100.00% 2 / 2 100.00% 1 / 1 2
 rethrowFailuresExceptAbandonedWaits 0.00% 0 / 5 0.00% 0 / 1 20
 holdDeliveries 100.00% 1 / 1 100.00% 1 / 1 1
 releaseDeliveries 100.00% 5 / 5 100.00% 1 / 1 2
 takeCompletedRuns 100.00% 3 / 3 100.00% 1 / 1 1
16final class HandlerFibers
17{
18    /** @var list<Future<mixed>> */
19    private array $suspended = [];
20
21    /** @var list<Closure(): void> */
22    private array $held = [];
23
24    private bool $holding = false;
25
26    /** @param Closure(): void $handler */
27    public function runSettled(Closure $handler): void
28    {
29        if ($this->holding) {
30            $this->held[] = $handler;
31
32            return;
33        }
34
35        $run = async($handler);
36        EventLoopTicks::settle();
37
38        if (!$run->isComplete()) {
39            $this->suspended[] = $run;
40
41            return;
42        }
43
44        $run->await();
45    }
46
47    public function rethrowFailures(): void
48    {
49        foreach ($this->takeCompletedRuns() as $run) {
50            $run->await();
51        }
52    }
53
54    public function rethrowFailuresExceptAbandonedWaits(): void
55    {
56        foreach ($this->takeCompletedRuns() as $run) {
57            try {
58                $run->await();
59            } catch (WaitException $e) {
60                if ($e->reason !== WaitError::Abandoned) {
61                    throw $e;
62                }
63            }
64        }
65    }
66
67    public function holdDeliveries(): void
68    {
69        $this->holding = true;
70    }
71
72    public function releaseDeliveries(): void
73    {
74        $this->holding = false;
75        $held = $this->held;
76        $this->held = [];
77
78        foreach ($held as $handler) {
79            $this->runSettled($handler);
80        }
81    }
82
83    /** @return list<Future<mixed>> */
84    private function takeCompletedRuns(): array
85    {
86        $completed = array_values(array_filter($this->suspended, static fn(Future $run): bool => $run->isComplete()));
87        $this->suspended = array_values(array_filter($this->suspended, static fn(Future $run): bool => !$run->isComplete()));
88
89        return $completed;
90    }
91}