Weak Reference support (now and future)
I built a data-binding system supporting one-way, two-way, and one-time assignment binding. It's integrated into an XML display list parser that supports construction of any object by using its fully-qualified class name as the tag name or through tag name aliases (e.g. "div" = "flos.gui.GUIControl"). It also supports string attribute value interpretation to strongly-type objects for pre-defined (object type/attribute name) pairs (e.g. turning "0,0,100,100" into a Rectangle when such a value is found on a DisplayObject's scrollRect attribute in the XML) as well as doing so dynamically for objects that implement an IAttributeParser interface: parse(name:String,value:String):*.
One issue I had to overcome was when using resolvable references for binding such as "<GUIControl name='page' topMargin='{bind this.menuBar.height}'/>" was "late binding", such that resolvable references were deferred to be resolved later, such as in my example where 'this.menuBar', being higher in the display depth, would be created after the 'page' control which flows underneath the menu bar. The deferred binding works well, and since the infrastructure even supports a constructor child node (with props: 0, 1, 2, etc.) for objects that require constructor parameters, it can also force immediate resolution of attribute values instead of delaying these.
Now, the main issue with this sort of binding system is that when you construct a display list from some XML and it has binding; how should one handle unbinding when display objects go out of scope? It would be self-defeating to allow binding to be set up so easily in the XML, only to have to force programmers to later lookup and manually unbind those attributes in code for any single object that may be removed from the display list.
I managed to solve that problem by ensuring that my Binding class and BindingDictionary classes (with its source to target and target to source reverse dictionaries) all used Weak References to the source objects. The Dictionaries which used the source objects as keys for the target object entires were simply instantiated by passing true to the constructor to use weak references for keys. The Binding and TargetSourceProperty instances which had a "source" property and the "PropertyReference" class which stored a base object and target property name, had to be updated to use a WeakReference for their "source" and "base" properties. Now, once the Binding is established, it allows (i.e. does not prevent) the source object to be garbage collected, the source dictionary entry vanishes automatically when the the source object is garbage collected, and if the source happened be a target as well, the entry is removed when it detects the target has been garbage collected (e.g. the WeakReference is discovered to be null when it attempts to assign a value to the target). It all works wonderfully.
I implemented a WeaKReference like so:
public class WeakReference
{
private var d:Dictionary;
public function WeakReference( obj:* )
{
if (obj == null)
throw new Error( "WeakReference target object cannot be null." );
d = new Dictionary( true ); //use weak keys
d[obj] = 0; //store obj as weak key with dummy content
}
public function get():*
{
for (var key:* in d) //if target object was garbage collected, dictionary will contain no keys since keys were weak references
return key;
return null;
}
}
It just seems like such a hack to have to use a whole Dictionary object to store one weak reference. Is there any other way to store a weak reference? Are there any plans to add better support for weak references in ActionScript?
As I've demonstrated, they are very important to this kind of system, where one must have the ability to establish bindings in XML, which will instanate objects that can be discarded without worrying about having to manually unbind everything to avoid memory leaks.
