1 Reply Latest reply on Jul 1, 2012 10:18 PM by Flex harUI

    Dictionary fails to use weak reference

    cdsvvxv

      ISSUE SOLVED

      -------------------

      This problem is now irrelevant as a much simpler way to fix the actual code I was working on has materialised. The solution does not involve a Dictionary class at all, and so the fix has not been posted. Howerver, this site states:

       

      By default the values in dictionaries are “strong” and you can specify a “weak” key, by doing this, you can actually make sure that if nothing else has a reference to ObjectX, it will get cleaned by the garbage collection. BUT, ObjectY will not get cleaned even though the key for it got cleaned from the dictionary.

       

      As I was doing:

       

      dictionary[person] = person;

       

      therefore it could be that GC was not running on person as the value may not have been cleared (only the key). I have not tested this theory.

       

       

      ORIGINAL QUESTION

      -----------------------------

       

      I am trying to use a Dictionary with a weak reference. This is the test code I wrote to check why my real code isn't working. When the 'Add person' button is clicked a new Person() Object is added to both an Array (people) and to the Dictionary. When the 'Remove person' button is clicked, a person is popped from the Array and nullified. Checking the Profiler the instance count of People  does not change even though the Dictionary is set to use weak references. According to the documentation:

       

       


      weakKeys:Boolean (default = false) — Instructs the Dictionary object to use "weak" references on object keys. If the only reference to an object is in the specified Dictionary object, the key is eligible for garbage collection and is removed from the table when the object is collected. Note that the Dictionary never removes weak String keys from the table.  Specifically in the case of String keys, the weak reference will never get removed from the key table, and the Dictionary will keep holding a strong reference to the respective values. 

       

      I have tried using both a String key and an Object key, neither seem to work.

       

      Note that although I call System.gc() in the code below, I am also using the Flash Develop profiler to check the instance count.

       

      Am I doing something wrong?

       

      -- Main.mxml ---

       

      <?xml version="1.0" encoding="utf-8"?>

      <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

                     xmlns:s="library://ns.adobe.com/flex/spark"

                     xmlns:mx="library://ns.adobe.com/flex/mx"

                     creationComplete="onCreationComplete()">

       

          <fx:Script>

              <![CDATA[

                  import flash.utils.Dictionary

                  import mx.utils.UIDUtil;

                  import util.Person;

       

                  private var dictionary:Dictionary;

       

                  private var people:Array;

       

                  public function onCreationComplete():void {

                      people = new Array();

                      dictionary = new Dictionary(true);

                  }

       

                  public function eventHandlerClickAdd():void {

                      // Create the person

                      var person:Person = new Person();

                      person.forename = Math.floor(Math.random() * 1000) + "";

                      person.surname = Math.floor(Math.random() * 1000) + "";

                      // Add them to the Array

                      people.push(person);

                      // Add them to the dictionary

                      //dictionary[UIDUtil.getUID(person)] = person;

                      dictionary[person] = person;

                      trace("Person added: people length now  [" + people.length + "]");

                  }

       

                  public function eventHandlerClickRemove():void {

                      if (people.length > 0) {

                          var person:Person = people.pop() as Person;

                          trace();

                          trace("-----");

                          person.toString();

                          trace("Person removed: people length now [" + people.length + "]");

                          person = null;

                          System.gc();

                          trace("");

                          trace("-- People still in dictionary are:");

                          var dictionaryCount:int;

                          for each(person in dictionary) {

                              person.toString();

                              dictionaryCount++;

                          }

                          trace("[" + dictionaryCount + "] people still in the dictionary");

                      }

                  }

              ]]>

          </fx:Script>

       

          <s:VGroup paddingTop="10" paddingRight="10" paddingBottom="10" paddingLeft="10">

              <s:Button label="Add person" click="eventHandlerClickAdd()" />

              <s:Button label="Remove person" click="eventHandlerClickRemove()" />

          </s:VGroup>

       

      </s:Application>

       

       

      --- Person.as ---

       

      package util {

       

          import mx.utils.ObjectUtil;

       

          /**

           *

           * @author

           */

          public class Person {

       

              public var forename:String;

              public var surname:String;

       

              public function Person() { }       

       

              public function toString():void {

                  trace(ObjectUtil.toString(this));

              }

          }

      }

       

      --- Output ---

       

      Person added: people length now  [1]

      Person added: people length now  [2]

      Person added: people length now  [3]

      Person added: people length now  [4]

      Person added: people length now  [5]

       

      -----

      (util::Person)#0

        forename = "389"

        surname = "819"

      Person removed: people length now [4]

       

      -- People still in dictionary are:

      (util::Person)#0

        forename = "389"

        surname = "819"

      (util::Person)#0

        forename = "231"

        surname = "623"

      (util::Person)#0

        forename = "23"

        surname = "90"

      (util::Person)#0

        forename = "554"

        surname = "443"

      (util::Person)#0

        forename = "448"

        surname = "877"

      [5] people still in the dictionary