Boost logo

Boost :

From: Rani Sharoni (rani_sharoni_at_[hidden])
Date: 2003-12-11 11:44:02


Peter Dimov wrote:
> Rani Sharoni wrote:
>> Peter Dimov wrote:
>>> Have you read
>>>
>>> http://www.boost.org/libs/smart_ptr/sp_techniques.html
>>
>> Thanks for this awesome usability demonstration!
>> Maybe it will help me to convince some people in my work place to
>> start using shared_ptr.
>>
>> I have few comments regarding failure guaranties. In general I think
>> that weakening failure guarantee is something that should be avoided
>> and I saw few places in your paper in which adding shared_ptr changed
>> the failure guarantee from no-fail into fail with std::bad_alloc
>> since share_ptr constructor might throw it.
>
> This may indeed be a potential problem, but in practice...
>
>> For example:
>> 1) Using shared_ptr as CopyConstructible mutex lock: lock had no fail
>> guarantee.
>
> Acquire-style functions such as lock() typically don't need the
> nothrow guarantee; unlock() does. If a nothrow lock() is important,
> the lock object would need to be moveable. ;-)

Sorry but I personally can't program with lock that might fail and handle
the failure. This will definitely change the non failure guarantee of many
functions/scopes such as cleanup functions and non-mutating functions. Sure
that there are cases in which the lock will not change the failure guaranty.

>> 2) Using shared_ptr to wrap member function calls: operator-> might
>> have no fail guarantee. E.g. pointer<X> p; p->cleanup();
>
> Correct, the quick shared_ptr solution has a problem with nothrow
> regions when prefix() is nothrow. A better pointer<> would be
> moveable, and more complicated.
>
>> 3) Delayed deallocation: Y::f() called px.reset that had no fail and
>> vector::push_back might throw.
>
> This is fortunately not a problem. Had Y::f() been nothrow, the only
> fix needed is to wrap push_back in a try-catch(...) {} block, falling
> back to immediate deallocation when the free list is "full".

In such situations I prefer to use containers with non-failing insert
operation such as intrusive link list (BTW – I didn't saw such containers in
boost).

>> One question: why shared_count::shared_count(weak_count const &)
>> throws boost::bad_weak_ptr and what can be done when catching such
>> exceptions?
>
> The corresponding nothrow equivalent is weak_ptr::lock:
>
> if( shared_ptr<X> px = wp.lock() )
> {
> // do something with *px
> }
> else
> {
> // handle the wp.expired() case
> }

In many cases that I've encountered, this indicates about programming error
but this can be easily refined using wrapper that asserts on the validity of
the pointer.

> The constructor should be used in situations where, well, an expired
> weak_ptr should cause an exception. :-)

My concern that it might become like Java cast that might fail yet I assume
that many programmers doesn't realize that it changes their failure
guarantee and therefore probably affect the correctness of their
programmers. The power and weakness of implicit failure handling.

> For example, let's say that you have a list of function objects that
> need to be invoked periodically (once per second, or once per frame.)
> Some of these function objects may, directly or indirectly, hold weak
> pointers to objects in the "application world". When such a weak
> pointer expires, the function object throws bad_weak_ptr from its
> operator(), and you respond by removing it from the list.

Thanks for the example.

>> It seems to have potential impact on the failure guaranty
>> of many functions such as impl::getX (Obtaining a shared_ptr to
>> this).
>
> In this case, bad_weak_ptr signals that the object is not managed by a
> shared_ptr, i.e. a programming error.

I'm surprised to see that you accept that programming error might trigger an
exception especially since http://tinyurl.com/yrxs significantly affected my
mind set about contact violations.
I've come to realize that programming error (i.e. bugs) are out of the scope
of the language and therefore no heroic effort to programmatically handle
them is needed, the environment should handle the termination of the program
with optional tracing help (e.g. create dump or launch a debugger).

Thanks,
Rani


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