rfc:weakreferences
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:weakreferences [2011/07/15 17:18] – created colder | rfc:weakreferences [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Request for Comments: Weak References | + | ===== Request for Comments: Weak References ===== |
- | * Version: 1.0 | + | * Version: 1.1 |
* Date: 2011-07-15 | * Date: 2011-07-15 | ||
- | * Author: Etienne Kneuss < | + | * Author: Etienne Kneuss < |
- | * Status: | + | * Status: |
===== Introduction ===== | ===== Introduction ===== | ||
- | This RFC discuss | + | Weak references is an established concept in many existing object oriented languages such as [[http:// |
- | ==== Weak Reference ==== | + | [[https:// |
- | A weak reference is a reference to an object that does not prevent its collection from the garbage collector (GC). Weak references are trying to solve the problem of caches and secondary references in complex data-structures. In such scenarios, the cache prevents the garbage collector from collecting an object, even though it's explicit usage has stopped. | + | __Notes:__ |
- | ==== Use Cases ==== | + | * Weak references does not change the behavior of normal (" |
+ | * There is currently no mechanism in PHP that you can use to implement weak references. You need to reference an object to access it. The garbage collector needs the object to not be referenced to collect it. Ergo you cannot both reference an object and have the garbage collector collect it. | ||
+ | * Weak references is not used to enable or implement caching. Rather the opposite: weak references is used to prevent caching of objects. | ||
- | Weak references are useful to allow associating data to existing objects, without having to manually clean this information before the actual object gets collected. | + | ===== Use Cases ===== |
+ | Because weak references is such a generic concept it would be hard to find a use case that's both generic enough to cover most use cases and specific enough too allow you to relate to them. This section contains three use cases that the RFC author thinks would be among the most relevant for userland developers, but there could also be other useful usages. This section attempts to describe three major ones in an abstract way and provide concrete examples for them. | ||
+ | |||
+ | ==== Remote-identifier-indexed index ==== | ||
+ | |||
+ | When designing applications that fetch and model objects from external data sources an identifier is used to recognize this object. In a database it could be an ID while a file system would use the file name. One example could be an external server that takes a serial number of a product and return the related product data. The application might want to fetch the same serial number multiple times. Fetching the same product again and making a new object could have several problems. It might be slow and expensive. It might also break the assumption that an " | ||
+ | |||
+ | In a MVC (Model, View, Controller) framework one design is to have an internal dictionary of ID's that maps to their respective fetched model instances so an already fetched and initialized model instance can be returned when the application requests the same ID multiple times. However this design will prevent the garbage collector from actually freeing the objects when they are no longer used. Imagine that a web application quickly loops through all instances in a large table - examining them one at a time. Suddenly the application crashes due to an OOM (out of memory). This is because the internal ID index acts as a cache rather than a weak index collection. The hard references prevents the objects from being freed after they have been fetched from the database. If the index was a weak reference collection instead this would not be a problem. | ||
+ | |||
+ | ==== The observer pattern ==== | ||
+ | |||
+ | One useful design pattern is having object listening to events of other objects. This is known as the " | ||
+ | |||
+ | An airplane company Flight Inc. has a PHP application with a Flight class and a SeatBooking class. Whenever a Flight is set to " | ||
+ | |||
+ | The programmer is now given another task - to loop trough all potential SeetBooking' | ||
+ | |||
+ | Also see the current interfaces that SPL already provides for the observer pattern: [[http:// | ||
+ | |||
+ | ==== Non-obtrusively associating data with objects ==== | ||
+ | |||
+ | Arbitrarily associating data with objects is easier in PHP than other more strict languages since PHP allows dynamically adding public properties to object at run time. However doing this can still be undesirable in third party classes for several reasons: | ||
+ | |||
+ | * It can easily result in unintended side effects (bugs). The property might be subtly used (dynamically) and the property might be reserved in future updates. | ||
+ | * Awkward underscore prefixing to avoid the above. | ||
+ | * The class (or another class) might reflect on its properties - resulting in unintended side effects. | ||
+ | * The class might not allow dynamically adding properties. (overloaded get/set) | ||
+ | * Adding properties could have special meaning in the class. (overloaded get/set) | ||
+ | * Dynamically re-designing third party classes is not generally regarded as good object oriented design (" | ||
+ | * Not fully understanding the data structure or object graph in third party library being modified could result in memory leaks. | ||
+ | |||
+ | To solve this one can use a dictionary and map the object to the related data. In PHP this can be achieved by using [[http:// | ||
+ | |||
+ | ===== Proposal and Patch ===== | ||
+ | |||
+ | This RFC suggests adding a class called " | ||
+ | |||
+ | void | ||
+ | object SplWeakRef:: | ||
+ | bool | ||
+ | | ||
+ | Patch is available here: [[http:// | ||
+ | |||
+ | ==== Example ==== | ||
<?php | <?php | ||
Line 40: | Line 84: | ||
| | ||
unset($a); // destroys object | unset($a); // destroys object | ||
- | ===== Proposal and Patch ===== | ||
- | Proposal is a SplWeakRef class, which implements some magic to allow GC collection. SplWeakRef would have the following prototype: | + | ===== Additional cleanup and __destruct() ===== |
- | | + | Another common requirement will be to have the ability to clean up additional resources whenever the weakly reference object is collected - when SplWeakRef turns invalid. For example when implementing some sort of weak reference collection. In such a collection you would want to remove any weak reference that turns invalid to prevent references that take up resources. This RFC does not propose any mechanism in SplWeakRef to catch such an event for two reasons: First of all the initial version of SplWeakRef should be as simple as possible. Secondly there is a workaround. By utilizing the destruct() method on the object that is weakly referenced, one can catch this event and run any remaining cleanup. It might also be possible to make the collection more automated - for example, by using a third class as a proxy that is referenced both by the weak reference class and the target class - with a generic destruct() method. |
- | | + | |
- | | + | A future improvement would be to change the constructor (and implementation) to: |
- | + | ||
- | + | | |
- | Patch is available here: [[http://patches.colder.ch/php-src/weakref-trunk.patch? | + | |
+ | If the SplWeakRef | ||
+ | |||
+ | Note that resurrection must be avoided so the SplWeakRef | ||
+ | |||
+ | ===== Further reading ===== | ||
+ | |||
+ | | ||
+ | * http:// | ||
+ | * http://msdn.microsoft.com/en-us/library/ | ||
+ | |||
+ | ===== References ===== | ||
+ | * [1] https:// | ||
+ | * [2] https:// | ||
+ | * [3] http:// |
rfc/weakreferences.1310750331.txt.gz · Last modified: 2017/09/22 13:28 (external edit)