Boost logo

Boost :

From: Mark Borgerding (mborgerding_at_[hidden])
Date: 2000-03-04 11:07:07


Jens Maurer wrote:

> "Borgerding, Mark A." wrote:
> > Approach #1)
> > Notify everybody.
> >
> > In this approach, every linked_ptr to a given heap object would be
> > nullified. The problem with this is that it could have unexpected results
> > in other threads.
>
> If this happens, you haven't made your software specification
> airtight enough anyway: You're passing ownership of the
> pointer to some library function out of your control, so
> it's always a bug to dereference the pointer afterwards. Thus,
> the null-pointer bang is justified. This reasoning works
> both in the threading and non-threading cases. To support the
> usage "if(p.get()) p->do()" in the threading case would require
> to be able to "lock" the pointer (and defer release() operations
> in other threads while locked). This is a new interface
> requirement.

I can't imagine having a lockable smart pointer. For me, this is just getting
way out of the scope of what a smartpointer should do.

> > Aprroach #3)
> > release only if unique() is true
>
> > By using the return code of release to find out if the object was the last
> > reference, a user can avoid dangling pointers.
>
> We agree on this.
>
> > -Slight bias toward double-deletion
>
> I don't see why. If release() returns 0, we simply cannot pass
> ownership to an auto_ptr<>, so we cannot call our library function.
> Where's the "double delete" happening?
>

I'm saying that there is a slight bias toward double deletion because a previous
dumb pointer that could have been received by get() , but I guess any smart
pointer implementation has this danger.

> > All things considered, the conditional release may be a little less
> > powerful, but it is a lot more stable and predicatble than the other
> > approaches.
>
> I'm arguing that the case where unique() is true is so rare in real
> shared_ptr<> usage that it's purely academic to have an approach #3
> release().
>

It allows the user to perform a release only when it is safe. If that is a rare
case, then all the more reason to make release strict. Otherwise it could be an
invitation to hard to find errors.

I am invisioning usage something like the following. Beware, this is a quickly
contrived example, and it shows :)

Let's say there is a 3rd party LibraryCall that takes a thingie*. It uses it and
then deletes it.

for (vector<shared_ptr<thingie> >::iterator it = things.begin() ; it !=
things.end() ; ++it)
{
    thingie * pT;
    if ( it->unique() )
        pT = it->release();
    else
        pT = new thingie(*pT); // someone else is using it, so make a copy
   LibraryCall(pT);
}

This allows us to avoid a copy constructor when possible, and use one when
necessary.

I would explore this more, but I promised my wife I would clean today.

- Mark


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk