src/WeakReferenceStasis.php source

1 <?php
2
3 declare(strict_types=1);
4
5 namespace Serializor;
6
7 use WeakReference;
8
9 /**
10 * Stasis for WeakReference objects.
11 * Preserves weak reference semantics - if the referenced object isn't
12 * strongly referenced elsewhere, the reference becomes dead.
13 */
14 final class WeakReferenceStasis extends Stasis
15 {
16 private ?object $ref = null;
17 private bool $dead = false;
18
19 private function __construct() {}
20
21 public function __serialize(): array
22 {
23 if ($this->dead) {
24 return ['d' => true];
25 }
26 return ['r' => $this->ref];
27 }
28
29 public function __unserialize(array $data): void
30 {
31 $this->dead = $data['d'] ?? false;
32 $this->ref = $data['r'] ?? null;
33 }
34
35 public function getClassName(): string
36 {
37 return WeakReference::class;
38 }
39
40 public static function fromWeakReference(WeakReference $value): WeakReferenceStasis
41 {
42 $frozen = new WeakReferenceStasis();
43 $frozen->ref = $value->get();
44 return $frozen;
45 }
46
47 /**
48 * Mark this weak reference as dead (target not strongly referenced).
49 */
50 public function markDead(): void
51 {
52 $this->dead = true;
53 }
54
55 /**
56 * Get the referenced object for strong reference tracking.
57 */
58 public function getRef(): ?object
59 {
60 return $this->ref;
61 }
62
63 public function &getInstance(): mixed
64 {
65 if ($this->hasInstance()) {
66 return $this->getCachedInstance();
67 }
68
69 if ($this->dead || !\is_object($this->ref)) {
70 // Create a dead WeakReference
71 $temp = new \stdClass();
72 $result = WeakReference::create($temp);
73 unset($temp);
74 } else {
75 $result = WeakReference::create($this->ref);
76 }
77
78 $this->setInstance($result);
79 return $result;
80 }
81 }
82