From 67362673888202bd5fd9dcfbc8bdb20780c95924 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Tue, 15 Apr 2008 21:08:25 +0000 Subject: [PATCH] Jamie has discovered that the MultiLoader can sometimes be gc'd before calling the callback. Loaders are not supposed to do this, but that may only be when loading over the network and not from a ByteArray. We know that retaining a reference to the MultiLoader fixes it, but that increases the burden on the users of this class. Let's try this instead, I think it will work: just retain references to active MultiLoaders in the class. Jamie's going to test this, as well. (Also: in foreach mode, free references to results after reporting them.) git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4999 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- src/as/com/threerings/util/MultiLoader.as | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/as/com/threerings/util/MultiLoader.as b/src/as/com/threerings/util/MultiLoader.as index 3818d6a3e..93c32b24e 100644 --- a/src/as/com/threerings/util/MultiLoader.as +++ b/src/as/com/threerings/util/MultiLoader.as @@ -219,6 +219,11 @@ public class MultiLoader if (!_forEach) { checkReport(endCheckKey); } + + // if we're not done at this point, keep a reference to this loader + if (_remaining > 0) { + _activeMultiLoaders[this] = true; + } } protected function handleError (event :ErrorEvent) :void @@ -246,6 +251,19 @@ public class MultiLoader trace("MultiLoader: Error calling completeCallback [result=" + thisResult + "]."); trace("Cause: " + err.getStackTrace()); } + + if (_forEach) { + delete _result[key]; // free the loaded object to assist gc + } + + // If we're all done, remove the static reference to this loader. + // Note that this could be called in for-each mode if we haven't yet started to load + // something asynchronously but have come across an Error or an already-completed load. + // That's ok, as this will just end up deleting a reference that doesn't exist, and if + // necessary the reference will still be added at the end of the constructor. + if (_remaining == 0) { + delete _activeMultiLoaders[this]; + } } /** @@ -277,5 +295,6 @@ public class MultiLoader protected var _remaining :int = 0; + protected static const _activeMultiLoaders :Dictionary = new Dictionary(); } }