On 2014-08-13, 8:14 AM, Aryeh Gregor wrote:
On Wed, Aug 13, 2014 at 9:42 AM, Jeff Walden <jwalden+...@mit.edu> wrote:
So at risk of adding yet another flavor of thing: why not introduce an 
already_AddRefed<T> sort of struct that *does* own an addref, *will* release on 
destruction if not nulled out, and does *not* explicitly convert to T*?  Give nsCOMPtr move 
constructors and move assignment operators from that class, that null out this other 
pointer when called, to transfer ownership at no cost.  (At risk of overplaying my hand, I 
think I've just described what WebBlink calls PassRefPtr, except for that pertaining to 
concrete classes whereas nsCOMPtr<T> is for abstract T classes.)

I recognize this introduces yet another way to do things.  But it enables 
incremental transition to a completely safe system that prohibits assignment of 
a method call to a raw pointer, and yet never has problems with leaks.  If we 
work hard at enforcing this on the way in, it can quickly become second nature, 
I think.

I think this can be improved upon a bit further: just change
already_AddRefed to behave more similarly to nsCOMPtr, but still not
convert to T* implicitly.  So for instance:

* Change ~already_AddRefed to just release the pointer instead of
asserting.  This means it would be perfectly okay to ignore the result
of a function that returns already_AddRefed.

What goal would this achieve? I don't understand why it's OK to ignore the return value of a function which returns an "already AddRef'ed" object from a conceptual perspective.

* Make an already_AddRefed constructor from T* (which would addref).
This allows you to return a raw pointer from a function with
already_AddRefed return type, and it will do the right thing without
you having to define an nsCOMPtr temporary.

already_AddRefed already has a constructor from T* which would not addref. Essentially this will mean not supporting dont_AddRef() any more. Why is that a good idea?

* Make an already_AddRefed constructor from nsCOMPtr/nsRefPtr (which
would addref if the source is an lvalue, and steal the value if the
source is an rvalue).  This allows you to return a local nsCOMPtr or
nsRefPtr directly, without having to call .forget().  If we want to be
extra careful to avoid accidental addrefs, we could allow construction
only from rvalues, but I'm not sure this is a good idea.

Hmm, so this would allow you to save typing ".forget()" when returning a COM/ref ptr? I actually think that the .forget() there is super helpful because it makes it clear that there is an ownership transfer going on. It's more cumbersome to type, but code is read more often than it's written and all. :-)

* Allow conversion of already_AddRefed to bool, and comparison to T*.

This I can get behind, but I'm not sure how useful it is without the other parts of your proposal.

This has most of the benefits of my original proposal, without the
drawback David and Ehsan object to.  It has the advantage of not
having to change the return type of a few thousand functions.  It has
the disadvantage that you could still not pass an already_AddRefed
directly to a function that wants T*, which is unfortunate because
it's perfectly safe to do so.  I can't think of any way to avoid that
except defining new types for refcounted parameters to use instead of
raw pointers (which would have other uses as well).

David, Ehsan, what do you think?

Honestly I'm struggling to decide which problems we _should_ solve here. I almost always prefer more explicit syntax (for example, having to type .forget()) when it comes to things such as ownership transfers. It makes it easier to spot things when reading the code, and it makes the author more conscious of what they're doing. I also think that you're essentially trying to eliminate the concept of a helper object that acts as a pipe of sorts to deliver the information that there is an ownership transfer happening by making already_AddRefed and nsCOM/RefPtr indistinguishable. Neither of these seem like improvements to me. I'm curious to know what others think about this.

Cheers,
Ehsan
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to