Boost logo

Boost :

From: David B. Held (dheld_at_[hidden])
Date: 2003-01-29 15:46:45


"David Abrahams" <dave_at_[hidden]> wrote in message
news:ufzrblnvz.fsf_at_boost-consulting.com...
> > [...]
> > Unfortunately, StoragePolicy doesn't know when other c'tors have
> > failed. The only one who does is smart_ptr, which is why it seems
> > I have to either A) use a function try block to inform StoragePolicy
> > that someone else has failed, and clean up appropriately,
>
> Why not just arrange for StoragePolicy to be the first constructed?

smart_ptr(T* p)
    : storage(p), ownership(p), conversion(), checking()
{ ... }

Suppose storage(p) succeeds, but ownership(p) throws (such as while
allocating a count). You can't rely on ~storage() to do cleanup, because
storage doesn't know what the ownership strategy is. It only knows
about storage. Here's what ~smart_ptr() looks like:

    ~smart_ptr()
    {
        if (ownership_policy::release(get_impl(*this)))
        {
            storage_policy::destroy();
        }
    }

So you see, storage_policy must be told when to do cleanup by
smart_ptr (that's the principle of orthogonal policies). It's easy
enough to write storage_policy::storage_policy(T* p) to clean up
after itself if *it* throws. But getting it to clean up after *another*
policy is the trick. Obviously, if one of the other c'tors throws,
~smart_ptr() never gets called, so how do we tell storage_policy
that a failure occurred, and it needs to clean up? The only way I
can see is to use a function try block:

smart_ptr(T* p)
try
    : storage_policy(p), ownership(p), conversion(), checking()
{ ... }
catch
{
    storage_policy::destroy();
}

Unfortunately, that's totally Greek to bcc 5.5 (and probably vc++,
though I don't have access to it right now), not to mention that it
requires storage_policy(p) to be no-throw.

> > or B) not use initializer lists, and do all the work in the c'tor
> > body of smart_ptr.
>
> I don't see how B can work; the resource will be unmanaged at
> least until the body is entered, while all the bases and members
> are constructed.

That can only work if the default c'tors are no-throw, which would
mean special-casing ref_counted to not allocate a count until it
actually receives a pointer. But it would also make the rest of the
functions in ref_counted bulkier because now you have to detect a
null count pointer. Otherwise, you would have to set the count
pointer to null, and have the body of smart_ptr ask ref_counted if
he was built properly. Quite messy. I don't see any nice solutions
to this problem.

Dave


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