4
4
[ ![ Windows Build status] ( https://ci.appveyor.com/api/projects/status/7r07eydi6c3lj36a/branch/master?svg=true )] ( https://ci.appveyor.com/project/pinepain/php-weak )
5
5
[ ![ GitHub license] ( https://img.shields.io/badge/license-MIT-blue.svg )] ( https://raw.githubusercontent.com/pinepain/php-weak/master/LICENSE )
6
6
7
- This extension provides [ weak references] ( https://en.wikipedia.org/wiki/Weak_reference ) support for PHP 7 and serves
8
- as a ground for other weak data structures.
7
+ This extension adds [ Soft Reference] ( https://en.wikipedia.org/wiki/Weak_reference ) and
8
+ [ Weak References] ( https://en.wikipedia.org/wiki/Weak_reference ) to PHP 7 and may serve as a ground for other
9
+ data structures that require advanced referencing model.
9
10
10
11
11
12
## Usage
@@ -14,12 +15,18 @@ as a ground for other weak data structures.
14
15
<?php
15
16
16
17
use Weak\Reference;
18
+ use Weak\SoftReference;
17
19
18
- $obj = new stdClass();
20
+ $obj = new class {
21
+ public function __destruct() {
22
+ echo 'Destructor called', PHP_EOL;
23
+ }
24
+ };
19
25
20
- $ref = new Reference($obj, function () { echo 'Object destroyed', PHP_EOL; });
26
+ $softref = new SoftReference($obj, function () { echo 'Object will be destroyed', PHP_EOL; });
27
+ $weakref = new Reference($obj, function () { echo 'Object destroyed', PHP_EOL; });
21
28
22
- $obj = null; // outputs "Object destroyed"
29
+ $obj = null; // outputs "Object will be destroyed", "Destructor called", "Object destroyed" in this specific order.
23
30
```
24
31
25
32
@@ -29,13 +36,15 @@ This extension adds `Weak` namespace and all entities are created inside it.
29
36
30
37
There are no INI setting or constants provided by this extension.
31
38
32
- Brief docs about [ ` Weak\Reference ` class ] ( ./stubs/weak/Reference.php ) and [ functions] ( ./stubs/weak/functions.php )
39
+ Brief docs about classes and [ functions] ( ./stubs/weak/functions.php )
33
40
may be seen in [ stub files] ( ./stubs/weak ) .
34
41
35
42
Short list if what provided by this extension is:
36
43
37
- - ` class Weak\Reference `
38
- - ` class Weak\NotifierException extend Exception `
44
+ - ` abstract class Weak\AbstractReference ` * may not be subclassed directly* [ doc] ( ./stubs/weak/AbstractReference.php )
45
+ - ` class Weak\SoftReference extends AbstractReference ` [ doc] ( ./stubs/weak/SoftReference.php )
46
+ - ` class Weak\Reference extends AbstractReference ` [ doc] ( ./stubs/weak/Reference.php )
47
+ - ` class Weak\NotifierException extend Exception ` [ doc] ( ./stubs/weak/NotifierException.php )
39
48
- ` function Weak\refcounted() `
40
49
- ` function Weak\refcount() `
41
50
- ` function Weak\softrefcounted() `
@@ -47,6 +56,13 @@ Short list if what provided by this extension is:
47
56
- ` function Weak\object_handle() `
48
57
- ` function Weak\is_obj_destructor_called() `
49
58
59
+ ### References
60
+
61
+ There are two type of reference provided by this extension: ` SoftReference ` and ` Reference ` . The main difference is that
62
+ ` SoftReference ` call it notifier before referent object will be destructed which allows to prevent object be destroyed,
63
+ while ` Reference ` call it notifier after referent object was destructed.
64
+
65
+ Note: What this extension provides aren't quite actual soft and weak references, but it comes close for most use cases.
50
66
51
67
### Notifiers
52
68
@@ -57,14 +73,14 @@ will return `null` (unless rare case when object refcount get incremented in des
57
73
somewhere else).
58
74
59
75
If object destructor or one or more notifiers throw exception, all further notifier callbacks will be called as if
60
- that exception was thrown inside ` try-catch ` block. In case one or more exception was thrown, ` Weak\NotifierException `
76
+ that exception was thrown inside ` try-catch ` block. In case one or more exceptions were thrown, ` Weak\NotifierException `
61
77
will be thrown and all thrown exceptions will be available via ` Weak\NotifierException::getExceptions() ` method.
62
78
63
79
64
80
### Cloning
65
81
66
- When ` Weak\Reference ` cloned, notifier cloned too, so when tracking object destroyed, both notifier will be called, but
67
- they will be invoked with different ` Weak\Reference ` objects.
82
+ When reference is cloned, notifier is cloned too, so when tracked object destroyed, both notifier will be called,
83
+ but they will be invoked with different reference objects.
68
84
69
85
``` php
70
86
<?php
@@ -105,14 +121,14 @@ $obj = null; // outputs "Own notifier called" and then "Object destroyed"
105
121
106
122
### Serializing
107
123
108
- Serializing ` Weak\Reference ` is prohibited. Attempting to implement the ` Serializable ` interface will lead to a
124
+ Serializing reference object is prohibited. Attempting to implement the ` Serializable ` interface will lead to a
109
125
fatal error.
110
126
111
127
112
128
## Stub files
113
129
114
- If you are also using Composer, it is recommended that you add the [ php-weak-stub] ( https://github.com/pinepain/php-weak-stubs )
115
- package as a dev-mode requirement. This provides skeleton definitions and annotations to enable support for auto-completion
130
+ If you are also using Composer, it is recommended to add the [ php-weak-stub] ( https://github.com/pinepain/php-weak-stubs )
131
+ package as a dev-mode requirement. It provides skeleton definitions and annotations to enable support for auto-completion
116
132
in your IDE and other code-analysis tools.
117
133
118
134
composer require --dev pinepain/php-weak-stubs
@@ -141,7 +157,7 @@ To install extension globally run
141
157
142
158
# sudo make install
143
159
144
- You will need to copy the extension config to your php dir, here is example for Ubuntu with PHP 7 from
160
+ You will need to copy the extension config to your php dir, here is example for Ubuntu with PHP 7.0 from
145
161
[ Ondřej Surý's PPA for PHP] ( https://launchpad.net/~ondrej/+archive/ubuntu/php ) :
146
162
147
163
# sudo cp provision/php/weak.ini /etc/php/mods-available/
@@ -160,23 +176,17 @@ You may also want to add php-weak extension as a [composer.json dependency](http
160
176
## Internals
161
177
162
178
` Weak\Reference ` class is implemented by storing tracked object handlers and then wrapping it original ` dtor_obj ` handler
163
- with custom one, which meta-code is:
179
+ with a custom one, which meta-code is:
164
180
165
181
``` php
166
182
$exceptions = [];
167
183
168
- try {
169
- run_original_dtor_obj($object);
170
- } catch(Throwable $e) {
171
- $exceptions[] = $e;
172
- }
173
-
174
- foreach($weak_references as $weak_ref_object_handle => $weak_reference) {
184
+ foreach($soft_references as $soft_ref_object_handle => $soft_reference) {
175
185
if (is_array($weak_reference->notifier)) {
176
- $weak_reference ->notifier[] = $weak_reference;
177
- } elseif (is_callable($weak_reference ->notifier)) {
186
+ $soft_reference ->notifier[] = $weak_reference;
187
+ } elseif (is_callable($soft_reference ->notifier)) {
178
188
try {
179
- $weak_reference ->notifier($weak_reference);
189
+ $soft_reference ->notifier($weak_reference);
180
190
} catch(Throwable $e) {
181
191
$exceptions[] = $e;
182
192
}
@@ -186,11 +196,38 @@ foreach($weak_references as $weak_ref_object_handle => $weak_reference) {
186
196
if ($exceptions) {
187
197
throw new Weak\NotifierException('One or more exceptions thrown during notifiers calling', $exceptions);
188
198
}
199
+
200
+ if (refcount($object) == 1) {
201
+ try {
202
+ run_original_dtor_obj($object);
203
+ } catch(Throwable $e) {
204
+ $exceptions[] = $e;
205
+ }
206
+
207
+ foreach($weak_references as $weak_ref_object_handle => $weak_reference) {
208
+ if (is_array($weak_reference->notifier)) {
209
+ $weak_reference->notifier[] = $weak_reference;
210
+ } elseif (is_callable($weak_reference->notifier)) {
211
+ try {
212
+ $weak_reference->notifier($weak_reference);
213
+ } catch(Throwable $e) {
214
+ $exceptions[] = $e;
215
+ }
216
+ }
217
+ }
218
+
219
+ if ($exceptions) {
220
+ throw new Weak\NotifierException('One or more exceptions thrown during notifiers calling', $exceptions);
221
+ }
222
+ } else {
223
+ // required while internally PHP GC mark object as it dtor was called before calling dtor
224
+ mark_object_as_no_destructor_was_called($object);
225
+ }
189
226
```
190
227
191
228
## Development and testing
192
229
193
- This extension shipped with Vagrant file which provides basic environment for development and testing purposes.
230
+ This extension shipped with Vagrant file which provides basic environment for development and testing purposes.
194
231
To start it, just type ` vagrant up ` and then ` vagrant ssh ` in php-weak directory.
195
232
196
233
Services available out of the box are:
@@ -208,12 +245,14 @@ between large variety of PHP versions.
208
245
209
246
## Reference:
210
247
248
+ [ Soft reference on Wikipedia] ( https://en.wikipedia.org/wiki/Soft_reference )
211
249
[ Weak reference on Wikipedia] ( https://en.wikipedia.org/wiki/Weak_reference )
212
250
213
251
#### In other languages:
214
252
215
253
##### Java:
216
254
255
+ - [ Class ` SoftReference<T> ` ] ( https://docs.oracle.com/javase/7/docs/api/java/lang/ref/SoftReference.html )
217
256
- [ Class ` WeakReference<T> ` ] ( https://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html )
218
257
- [ Guidelines for using the Java 2 reference classes] ( http://www.ibm.com/developerworks/library/j-refs/ )
219
258
- [ Strong, Soft, Weak and Phantom References] ( http://neverfear.org/blog/view/150/Strong_Soft_Weak_and_Phantom_References_Java )
0 commit comments