@@ -7,7 +7,30 @@ final class Reaper
77 /** @var \WeakMap<object,list<self>> */
88 private static \WeakMap $ dd ;
99
10- private function __construct (private readonly \Closure $ callback ) {}
10+ private bool $ active = true ;
11+
12+ private function __construct (
13+ /** @var \Closure(): void */
14+ private readonly \Closure $ callback ,
15+ ) {}
16+
17+ /**
18+ * Detach the reaper from its target
19+ *
20+ * ```php
21+ * $a = (object) [];
22+ *
23+ * $reaper = Reaper::watch($a, function () { echo "Good Bye"; });
24+ * $reaper->forget();
25+ *
26+ * unset($b);
27+ * // prints nothing
28+ * ```
29+ */
30+ public function forget (): void
31+ {
32+ $ this ->active = false ;
33+ }
1134
1235 /**
1336 * Attach a callback to an object to be called when that object is destroyed.
@@ -52,16 +75,22 @@ private function __construct(private readonly \Closure $callback) {}
5275 *
5376 * @param callable(): void $callback
5477 */
55- public static function watch (object $ subject , callable $ callback ): void {
78+ public static function watch (object $ subject , callable $ callback ): self
79+ {
5680 self ::$ dd ??= new \WeakMap ();
5781
5882 self ::$ dd [$ subject ] ??= [];
5983
60- self ::$ dd [$ subject ][] = new self (\Closure::fromCallable ($ callback ));
84+ return self ::$ dd [$ subject ][] = new self (\Closure::fromCallable ($ callback ));
6185 }
6286
6387 /** @nodoc */
64- public function __destruct () {
88+ public function __destruct ()
89+ {
90+ if (!$ this ->active ) {
91+ return ;
92+ }
93+
6594 ($ this ->callback )();
6695 }
6796}
0 commit comments