Boost logo

Boost :

From: Pavel Vozenilek (pavel_vozenilek_at_[hidden])
Date: 2007-10-21 12:40:52

"Emil Dotchevski" wrote:
"Pavel Vozenilek" wrote:

>> 1. exception/exception.hpp (btw, this file name can easily confuse one
>> with
>> the same filename one level down) - assert() may be replaced with
>> BOOST_ASSERT or even better commented out. People may use their own
>> assert
>> implementation and this would make the exception module (something what
>> should be really the core part) dependent on something else.
> If there is a requirement for boost libraries to use BOOST_ASSERT,
> I'll make that change if the library is officially accepted in Boost.
No, there's no such requirement for BOOST_ASSERT and
the macro is not universally used.

I asked this because I use my own (feature rich) assert and
this implementation intentionally clashes with the default assert
and due to the structure of a project the best solution for me
was to remove the asserts from boost::exception (under assumption
there's no chance of them ever being triggered).

>> 2. shared_ptr<> may be replaced by intrusive_ptr<> or home made
>> equivalent.
>> This (a) reduces dependency on other Boost part (shared_ptr does depend
>> on
>> quite few other libs) and (b) the atomic locking used by shared_ptr would
>> be
>> eliminated. This would help a little bit on multiprocessor systems - lock
>> may be hundredths of cycles and during the time access to the memory bus
>> is
>> disabled.
> (a) is a valid concern, OTOH shared_ptr is such a low level component
> of Boost that -- as careful as I am in avoiding physical coupling -- I
> don't consider it a real dependency; rather, it's a tool for avoiding
> dependencies.
> (b) can be addressed if someone reports having performance issues with
> Boost Exception. This is highly unlikely since we're comparing the
> time it takes to copy a single shared_ptr once (at the time of the
> initial throw) vs. the time it takes for the implementation to unroll
> the stack until a suitable catch is found.

Ad (a) and Peter Dimov's reply: few years ago when I bcopy'ed shared_ptr
it depended on a lot of other code. This may be mistaken or obsoleted.

Ad (b): my personal opinion is that for such general purpose library people
would feel safer if it is reasonably optimized even for slow paths.

Other (over-)optimizations that may be considered:

* some to-string conversions could be handled w/o stringstream

* if it is applicable (I didn't measured) code bloat caused by
  inlining on slow paths may be reduced for MSVC compiled
  by using __declspec(noinline).

  Strange combination __declspec(noinline) inline void foo() {}
  is also possible with desirable effects

>> 1. As mentioned above, the ability to iterate through values and/or pass
>> a
>> visitor.
> Iteration presumes that you catch a boost::exception knowing nothing
> about the semantics of the actual exception type that was thrown, yet
> you want to make use of the data it contains.
> One use case would be to log all data contained in an (unknown)
> exception, for debugging purposes; this is supported by
> boost::exception::what().
> Another use case is when you want to catch exception type A and throw
> exception type B instead, such that the B object contains all the data
> from the A object plus some additional information. However, one of
> the motivations for Boost Exception is that it helps avoid the need to
> translate exception types, since you can catch A as boost::exception
> &, add whatever relevant data you have, and then re-throw the original
> A object.

Use case for iterator over values: I may want an automated checker
that verifies that exception A contains only somewhere specified values
and nothing else.

>> 4. I would like the ability to collect traces generated by what()
>> function
>> in DEBUG mode, something as:
>> catch (my_low_level_exception& e) {
>> my_high_level_exception e2;
>> ... fill in e2
>> e2.add_debug_trace(e); // adds e.what() somewhere, no-op in release
>> mode
>> throw e2;
>> }
> Would this work for you:
> struct tag_debug_trace: boost::error_info<std::string> { };
> void add_debug_trace( boost::exception & e2, boost::exception & e )
> {
> #ifdef _DEBUG
> if( !boost::get_error_info<tag_debug_trace>(e2) )
> e2 << boost::error_info<tag_debug_trace>("");
> (*boost::get_error_info<tag_debug_trace>(e2)) += e.what();
> #endif
> }
> and then:
> catch (my_low_level_exception& e) {
> my_high_level_exception e2;
> ... fill in e2
> add_debug_trace(e2,e);
> throw e2;
> }

Yeah, something like that with visual separation between different
exception objects and as a standard part of the library.


About an other poster wish for standardized stack trace: I wrote at least
stack trace libraries requiring manually added macro like
void foo() {

It would be handy to get something like that semi-standardized
next to the boost::exception and able to cooperate automatically with this

My implementation got quite complicated: thread safe, able to provide
one stack trace for

catch (exc1&) {
  throw exc2;

to store stack traces for sucessfully processed exceptions,
it was able to collect ad-hoc information like boost::exception can, etc.


Boost list run by bdawes at, gregod at, cpdaniel at, john at