|
2 | 2 |
|
3 | 3 | namespace TH\Maybe\Result; |
4 | 4 |
|
5 | | -use TH\Maybe\Result; |
| 5 | +use TH\ObjectReaper\Reaper; |
6 | 6 |
|
7 | 7 | /** @internal */ |
8 | 8 | trait MustBeUsed |
9 | 9 | { |
10 | | - /** @var \ArrayAccess<Result<mixed,mixed>,ResultCreationTrace>|null */ |
11 | | - private static ?\ArrayAccess $toBeUsed = null; |
12 | | - |
13 | | - /** |
14 | | - * @return \ArrayAccess<Result<mixed,mixed>,ResultCreationTrace> |
15 | | - */ |
16 | | - private static function toBeUsedMap(): \ArrayAccess |
| 10 | + /** @return \WeakMap<static,Reaper> */ |
| 11 | + private static function reapers(): \WeakMap |
17 | 12 | { |
18 | | - return self::$toBeUsed ??= self::emptyToBeUsedMap(); |
19 | | - } |
| 13 | + static $reapers; |
20 | 14 |
|
21 | | - /** |
22 | | - * @return \WeakMap<Result<mixed,mixed>,ResultCreationTrace> |
23 | | - */ |
24 | | - private static function emptyToBeUsedMap(): \WeakMap |
25 | | - { |
26 | | - /** @var \WeakMap<Result<mixed,mixed>,ResultCreationTrace> */ |
27 | | - return new \WeakMap(); |
| 15 | + return $reapers ??= new \WeakMap(); |
28 | 16 | } |
29 | 17 |
|
30 | 18 | /** |
31 | | - * Mark a result as needed to be used |
| 19 | + * Mark a result as needed to be used. Must be called at most once on an object. |
32 | 20 | */ |
33 | 21 | private function mustBeUsed(): void |
34 | 22 | { |
35 | | - self::toBeUsedMap()[$this] = new ResultCreationTrace(); |
| 23 | + $reapers = self::reapers(); |
| 24 | + |
| 25 | + if (isset($reapers[$this])) { |
| 26 | + throw new \LogicException('Object already register to be used'); |
| 27 | + } |
| 28 | + |
| 29 | + $creationTrace = new ResultCreationTrace(); |
| 30 | + |
| 31 | + $reapers[$this] = Reaper::watch($this, static fn () => throw new UnusedResultException($creationTrace)); |
36 | 32 | } |
37 | 33 |
|
38 | 34 | /** |
39 | | - * Mark a result as used |
| 35 | + * Mark a result as used. |
40 | 36 | */ |
41 | 37 | private function used(): void |
42 | 38 | { |
43 | | - unset(self::toBeUsedMap()[$this]); |
| 39 | + $reaper = self::reapers()[$this] ?? throw new \LogicException('Object not registered to be used'); |
| 40 | + $reaper->forget(); |
44 | 41 | } |
45 | 42 |
|
46 | 43 | public function __clone() |
47 | 44 | { |
48 | 45 | $this->mustBeUsed(); |
49 | 46 | } |
50 | | - |
51 | | - /** |
52 | | - * @throws UnusedResultException |
53 | | - */ |
54 | | - public function __destruct() |
55 | | - { |
56 | | - $map = self::toBeUsedMap(); |
57 | | - |
58 | | - if (isset($map[$this])) { |
59 | | - $creationTrace = $map[$this]; |
60 | | - unset($map[$this]); |
61 | | - |
62 | | - throw new UnusedResultException($creationTrace); |
63 | | - } |
64 | | - } |
65 | 47 | } |
0 commit comments