Boost logo

Boost :

Subject: Re: [boost] [Exception] Why is there no non-const versionofget_error_info?
From: Adam Badura (abadura_at_[hidden])
Date: 2009-08-20 17:59:05


    Taking into account our previous discussions I expected that you will
rather try to convince me that what I was going to do is bad rather then try
to add non-const get_error_info. :)

>From your description, it seems the first thing you need to consider
> is what is the exception safety guarantees of the function that
> notifies the listeners, as a whole.
>
> 1) If only basic exception safety guarantee is required, then you
> simply don't worry about the exceptions: if a onNotify throws, it'll
> propagate the exception out.
>
> 2) If strong exception safety guarantee is required, then you must
> make sure that if a onNotify throws, the effects of the already
> completed onNotifys can be undone without an error. Then, you
> propagate the exception as in 1).
>
> 3) Nothrow exception safety guarantee: you know onNotify won't throw.
>
> It seems you're leaning towards 3). If that's the case, if an onNotify
> throws, you have a bug. Therefore I don't think it is a good idea at
> all to "keep going". If I were you, I'd just catch(...) and assert(),
> possibly after logging
> boost::current_exception_diagnostic_information() somewhere.

    I thought about it a lot. :)

    And in this case it is not so simple. I would prefer 3) however I don't
thing that reasonable system can be done assuming 3) (without large risk of
exception data loss - since I consider premature excepting logging as
exception data loss). So 3) is not acceptable (especially taking into
consideration that standard gives almost no guarantees on exception throwing
so virtually anything non-trivial might possibly throw).
    2) would be great to. However is not possible as well. Mainly because
there are operations which might fail during reverting which defeats this
idea.
    So 1) is left and this is what I have now. But I would like something
better. I would like to notify all listeners even if they any of them fails.
Because this is what observable is supposed to do - notify listeners. If I
allow it to skip further onNotify calls once an exception is thrown I am in
a state which is almost surely unrecoverable because even if I deal somehow
with the error I have no way of continuing notifications from the interrupt
place. I could add such feature but it would be rather complex.

> That said, if you want to attach a bunch of exception_ptrs to a
> boost::exception, you could just use different tags:
>
> typedef boost:error_info<struct onNotifyFoo_,boost::exception_ptr>
> onNotifyFoo;
> typedef boost:error_info<struct onNotifyBar_,boost::exception_ptr>
> onNotifyBar;

    This obviously will not do since number of listeners is known at
runtime.

> Alternatively, you can collect them all into a
> std::vector<boost::exception_ptr>. When you're done calling onNotifys,
> if the vector is not empty you just throw an exception, adding the
> vector to it.
>
> If you are concerned about the (remote?) possibility of a
> std::bad_alloc propagating instead of your exceptions, you shouldn't
> be because that could happen anyway. To throw an exceptoin, the
> runtime needs memory to store the exception object. In some
> implementations that memory comes from the heap, so an attempt to
> throw any exception whatsoever could result in a std::bad_alloc
> instead (the runtime is required to have enough memory to throw a
> std::bad_alloc.)

    Yes. I described that method as an alternative. And yes I am concerned
with risk of std::bad_alloc. And yes I cannot avoid it fully anyway. But
Boost exceptions objects are small so the risk is marginal. And if this
happens anyway then I consider it an error so fatal that I will not recover
from it anyway - just unwind the stack. Just because you cannot avoid
accident does not meant that you will put yourself to an unnecessary risk,
right?

    Want another example? What about stack trace? I could have a sequence
container in the exception and in each catch in which I will rethrow the
exception I would add source code location data to have better diagnostic
information. Obviously I cannot do this with fixed number of separate
error_infos (without loss of data).
    And again I could each time get the stack trace, add new entry and reset
the stack trace with new collection. But with the same problems as
previously. Unnecessary risk of failure and decreased execution speed.

    But I will not only defend myself but rather strike back now! :) (Keep
in mind it is a joke!)
    What are the reasons to not have non-const get_error_info? I haven't
look into implementation but I guess it requires almost no work at all to
add (and maintain) it. I don't see also design purpose. If you allow to not
only modify once created exception object but also modify a const exception
object (I agree it is useful and convenient and I wouldn't like it being
removed) then you should allow to modify data in that object. I don't see
reason to treat the data in special way. Especially that after all I can
overwrite it with different value so in fact achieve the same but in less
efficient and safe method.

    Adam Badura


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