Date: Sun, 22 May 2005 00:21:21 +0100 From: Jean-Fran?ois Brouillet
Subject: [Boost-users] Re: ~intrusive_ptr bug? To: boost-users@lists.boost.org Message-ID: <76267242-0F5F-415A-A5ED-D671F4DE420F@mac.com> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed ... I fail to see the "generality" in the current design. An example where it actually makes sense to not "addRef" on ctor but to "remRef" on dtor would be most welcome. If you're arguing that the design of intrusive_ptr should be changed,
I don't have such pretensions. I was only suggesting to *rename* the parameter ``addRef'' into something less confusing because of the asymmetric behavior.
...
Many thanks. -- JFB
Here's my story:
I wrote my own "AutoRefCountPtr" before seeing boost::intrusive_ptr.
It is almost exactly the same as intrusive_ptr, including the addRef.
Here's why I need the addRef:
I'm using a library (DLL) that only exposes abstract classes (in the h
file). To get a 'real' object/implementation, I call a function to
create an object:
CreateFoo(fooparams,..);
Internally, this creates a Foo_Implementation, but it is returned to
me as a Foo *. Part of Foo's interface is reference counting, via
foo->AddRef() and foo->RemoveRef(). So when I'm done with Foo, I call
RemoveRef. Note, however, that the Foo * returned from CreateFoo is
already addRef'd and ready to go. So I don't need to call AddRef.
I could (and did for a while) manage my Foo*'s manually, but after
a number of leaks, I gave up and wrote a smart ptr (AutoRefCountPtr)
that would RemoveRef automatically when I was done with the pointer.
So there's your example.
I few other notes:
1. maybe CreateFoo() should have returned a AutoRefCountPtr for me,
instead of a 'naked' Foo *. But this is a bit hard, because CreateFoo
is inside the DLL, and doesn't really want to pass back any 'real'
objects (beside abstract interfaces) because the DLL and the EXE may
be built differently, not at the exact same version, etc.
2. maybe the whole system suffered from a fundamental design flaw, and
is a bad example. That could be, but nonetheless, it was an essential
library, and I didn't really have the option to NOT use it or rewrite
it, so an intrusive_ptr like thing was 'real world' helpful, even if
only to assist in living with a design flaw. (Not that I think there
was a design flaw, but even if there was...)
3. Note that, like intrusive_ptr, my ptr made the initial 'addRef'
optional. It needed to be false when you created the object, but if
Foo * was passed in as a function argument, that function might wrap
it in an intrusive_ptr that DID need to do the initial addref.
4. I called my flag 'addRef'. Is that exactly the same as
intrusive_ptr? Note that this still doesn't mean it is a good name -
I was the *implementor* and it made sense to me, and was very
descriptive for the *implementation*. But maybe it wouldn't make
sense for the client/user (which was also me, in my case :-). I
suspect boost's 'addRef' was also named from an implementation rather
than usage point of view. But I'm still not sure what a better name
would be. Maybe "already_pre_addRefd_thanks' or something like that?
I do sometimes agree with names that are NOT exactly obvious as long
as they are interesting enough that the user is likely to dig a little
deeper to find the meaning. But my co-workers often disagree...
p.s. I originally made my flag a template parameter, partially
because I like this syntax so much:
if (AutoRefCountPtr