Re: Leaks in nsSessionStore.js?
"Michael Vincent van Rantwijk, MultiZilla" <[email protected]> Fri, 16 Nov 2007 18:56:06 +0100
| Newsgroups | gmane.comp.mozilla.performance |
|---|---|
| Message-ID | <[email protected]> |
Jeff Walden wrote:
> Michael Vincent van Rantwijk, MultiZilla wrote:
>> http://lxr.mozilla.org/seamonkey/source/browser/components/sessionstore/src/nsSessionStore.js#177
>
>
> Note the third parameter is |true|. Looking at the IDL:
>
>> If set to false, the nsIObserverService will hold a strong reference
>> to |anObserver|. If set to true and |anObserver| supports the
>> nsIWeakReference interface, a weak reference will be held. Otherwise
>> an error will be returned.
>
> The idea of a weak reference is that you don't increment the refcount --
> you create an object which stores a pointer to whatever it is you want
> and return it instead. Given that object, you call QueryReferent(iid)
> on it to get a strong reference, which only then increments the
> pointer. The key to keeping this pointer from going stale on you is
> that when the actual object dies, its destructor will null out the
> pointer in the object you hold, so you can't use the dead pointer. One
> other thing to note is that you only ever need one weak reference object
> no matter how many places might want one, so if you need a weak
> reference, you can be given the existing one.
>
> The details are in
> <http://mxr.mozilla.org/mozilla/source/xpcom/glue/nsWeakReference.cpp>;
> I highly recommend spending half an hour or so reading it and figuring
> out how it works for the "aha!" moment you'll have.
>
> Anyway, back to the question: the call says |this| implements
> nsISupportsWeakReference. In C++ this would just be by inheriting from
> nsSupportsWeakReference, and in JS it's by having a QueryInterface which
> returns |this| when the provided IID is nsISupportsWeakReference. Since
> we have the latter, XPConnect will make the wrapper implement
> nsISupportsWeakReference, and if that wrapper goes away because its
> refcount reaches zero, it'll clear the pointer stored in the one weak
> reference the prefbranch has, and since the prefbranch thus no longer
> has a pointer, no cycle occurs.
>
> This is all a bit confusing, but I'm not sure there's really a good way
> to explain it -- you just need to stare at it for awhile until it makes
> sense.
>
> Jeff
Thanks you so much Jeff,
First, I now understand that the weak versus strong reference is about
owning it, and having a proxy for the object, presumably saving memory
and speeding things up a few milliseconds.
I was also able to convert my own XPCOM components to use weak
references i.e. by using |true| as third parameter, and by adding:
QueryInterface: function(aIID)
if (aIID.equals(Ci.nsIMyService) ||
aIID.equals(Ci.nsIObserver) ||
+ aIID.equals(Ci.nsISupportsWeakReference) ||
aIID.equals(Ci.nsIProfileStartupListener) ||
aIID.equals(Ci.nsISupports))
return this;
However, what I still fail to understand is _when_ I should (must?) use
weak references instead of a strong one; because most observers in the
CVS tree seem to be using a strong reference.
Also, is it possible that I use a weak reference which somehow gets
cleared, giving me a nsnull instead of a proxied object?
--
Michael Vincent van Rantwijk
- MultiZilla Project Team Lead
- XUL Boot Camp Staff member (ActiveState Training Partner)
- iPhone Application Developer