[exception] library update

I've finished a major refactoring of the Exception library: 1) Thanks to Peter Dimov's boost/detail/sp_typeinfo.hpp, it now works with or without RTTI support. 2) I would like to thank Dave and Robert for complaining about the added weight to boost/throw_exception.hpp. I managed to reduce that cost to less than 400 lines total, all contained in boost/exception/exception.hpp which now does not #include anything (not even standard headers.) If there are more concerns about this issue, let's discuss them now. The latest documentation can be viewed at http://svn.boost.org/svn/boost/trunk/libs/exception/doc/boost-exception.html. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

----- Original Message ----- From: "Emil Dotchevski" <emil@revergestudios.com> To: <boost@lists.boost.org> Sent: Monday, September 08, 2008 7:59 PM Subject: [boost] [exception] library update
2) I would like to thank Dave and Robert for complaining about the added weight to boost/throw_exception.hpp. I managed to reduce that cost to less than 400 lines total, all contained in boost/exception/exception.hpp which now does not #include anything (not even standard headers.) If there are more concerns about this issue, let's discuss them now.
I don't know if this will be enough. For me the semantics has ben changed, Robert has already created its own serialization::throw_ewception which is a copy of the old boost::throw_exception, who will be the next? IMO, we need to provide the old boost::throw_exception publically on boost, even if we change its name, before each library developer and user define its own throw_ewception. Can you provide some performance results comparing the old and the new implementations? Regards, Vicente

On Mon, Sep 8, 2008 at 10:31 PM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
I don't know if this will be enough. For me the semantics has ben changed
Could you please elaborate on this? (Hint: one possible definition of changed semantics is that the current behavior of boost::throw_exception is incompatible with the the previously documented behavior.)
Robert has already created its own serialization::throw_ewception which is a copy of the old boost::throw_exception, who will be the next?
There are also Boost libraries that use throw directly, without calling any function. If there is a requirement for all Boost libraries to throw using boost::throw_exception, I'm certainly not aware of it. If users care about the benefits of the "new" boost::throw_exception behavior (if it stays, which is obviously subject to discussion), they will complain that the Serialization or some other library doesn't call it. If not, all is good. :)
IMO, we need to provide the old boost::throw_exception publically on boost, even if we change its name, before each library developer and user define its own throw_ewception.
What reasons do you have for avoiding the current throw_exception behavior?
Can you provide some performance results comparing the old and the new implementations?
1) The performance cost of the current boost::throw_exception compared to the previous boost::throw_exception is the added zeroing of 3 pointers and an int. 2) Even if there was a measurable degradation in performance, it only occurs if an exception is being thrown. Therefore, it has to be compared to the overall speed of propagating an exception up the call stack (hint: often, this is a rather slow process.) There are two valid concerns with the "new" boost::throw_exception: A) Source code bloat: throw_exception.hpp is a major coupling point in Boost and as such, anything included by it has the potential of being included by many libraries, and, due to the mostly header-only nature of Boost, by the end user. Here is some cold data: on my system, preprocessing throw_exception.hpp results in ~30,000 lines of code, of which the added weight of boost/exception/exception.hpp is ~400 lines. Of course, throw_exception.hpp itself doesn't do anything. Including something that's actually useful yet minimal -- for example intrusive_ptr.hpp -- equals ~40,000 lines of code; shared_ptr.hpp: ~55,000 lines. In this case, the overhead is < 1%. B) Maintenance problems: we've already seen one bug in throw_exception.hpp escape undetected by our testing process, until it was reported by the end users. Clearly, any change in boost/exception/exception.hpp has the potential of breaking many libraries which -- I know -- is a major headache. So what's the upside? - The ability to transport Boost exceptions between threads. - The ability to catch any (well, most) Boost exceptions. - The ability to augment active exception objects with important information that is relevant to the failure but is not available at the point of the throw. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

----- Original Message ----- From: "Emil Dotchevski" <emil@revergestudios.com> To: <boost@lists.boost.org> Sent: Tuesday, September 09, 2008 8:46 AM Subject: Re: [boost] [exception] library update
On Mon, Sep 8, 2008 at 10:31 PM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
I don't know if this will be enough. For me the semantics has ben changed
Could you please elaborate on this? (Hint: one possible definition of changed semantics is that the current behavior of boost::throw_exception is incompatible with the the previously documented behavior.)
The previous documented semantics do not requires that the exception parameter should be derived from std::exception "When BOOST_NO_EXCEPTIONS is not defined, boost::throw_exception(e) is equivalent to throw e. Otherwise, the function is left undefined, and the user is expected to supply an appropriate definition. Callers of throw_exception are allowed to assume that the function never returns; therefore, if the user-defined throw_exception returns, the behavior is undefined."
Robert has already created its own serialization::throw_ewception which is a copy of the old boost::throw_exception, who will be the next?
There are also Boost libraries that use throw directly, without calling any function. If there is a requirement for all Boost libraries to throw using boost::throw_exception, I'm certainly not aware of it.
If users care about the benefits of the "new" boost::throw_exception behavior (if it stays, which is obviously subject to discussion), they will complain that the Serialization or some other library doesn't call it. If not, all is good. :)
If users care about the benefits of the "old" boost::throw_exception behavior they will complain and finish to use the boost::serialization::throw_exception.
IMO, we need to provide the old boost::throw_exception publically on boost, even if we change its name, before each library developer and user define its own throw_ewception.
What reasons do you have for avoiding the current throw_exception behavior?
I have any, but unser a specific name e.g. boost::exception::throw_exception. What reasons do you had for avoiding the old throw_exception behavior?
Can you provide some performance results comparing the old and the new implementations?
1) The performance cost of the current boost::throw_exception compared to the previous boost::throw_exception is the added zeroing of 3 pointers and an int.
2) Even if there was a measurable degradation in performance, it only occurs if an exception is being thrown. Therefore, it has to be compared to the overall speed of propagating an exception up the call stack (hint: often, this is a rather slow process.)
There are two valid concerns with the "new" boost::throw_exception:
A) Source code bloat: throw_exception.hpp is a major coupling point in Boost and as such, anything included by it has the potential of being included by many libraries, and, due to the mostly header-only nature of Boost, by the end user.
boost::exception::throw_exception would offer the same.
Here is some cold data: on my system, preprocessing throw_exception.hpp results in ~30,000 lines of code, of which the added weight of boost/exception/exception.hpp is ~400 lines. Of course, throw_exception.hpp itself doesn't do anything. Including something that's actually useful yet minimal -- for example intrusive_ptr.hpp -- equals ~40,000 lines of code; shared_ptr.hpp: ~55,000 lines. In this case, the overhead is < 1%.
Why to pay for +1% when I don't need if I can pay 0%?
B) Maintenance problems: we've already seen one bug in throw_exception.hpp escape undetected by our testing process, until it was reported by the end users. Clearly, any change in boost/exception/exception.hpp has the potential of breaking many libraries which -- I know -- is a major headache.
BTW, are we testing on a compiler without exception support and BOOST_NO_EXCEPTION defined? Do we have some tests on these configuration?
So what's the upside?
- The ability to transport Boost exceptions between threads.
The ability to transport every exceptions, and not only Boost exceptions, must be on the current_exception function, not on the throw_exception function. There is no throw_exception onthe proposed standard! If I need to use throw_exception to ensure this, I need to add a try-catch which is much more expensive than storing thre pointers, and this must be done independently if a exception is thrown.
- The ability to catch any (well, most) Boost exceptions. - The ability to augment active exception objects with important information that is relevant to the failure but is not available at the point of the throw.
I agree with you that boost::exception give these abilities, and I really think that this class is a very interesting. When a user want to use these abilities what he needs is just to use it directly. That's all! I really think that boost::throw_exception should preserv its old behavior (semantics), and the current_exception should be able to return an exception_ptr to the current exception for any exception. I have proposed a way to achieve this, but you have not made any comment on this. Vicenet

vicente.botet:
The previous documented semantics do not requires that the exception parameter should be derived from std::exception
They do, it just wasn't explicitly stated, and wasn't tested (which allowed one to throw enums by mistake). If 'e' doesn't derive from std::exception, the code won't compile when BOOST_NO_EXCEPTIONS is defined, and the original purpose of boost::throw_exceptions was precisely to support the case when BOOST_NO_EXCEPTIONS is defined.

----- Original Message ----- From: "Peter Dimov" <pdimov@pdimov.com> To: <boost@lists.boost.org> Sent: Wednesday, September 10, 2008 11:42 AM Subject: Re: [boost] [exception] library update
vicente.botet:
The previous documented semantics do not requires that the exception parameter should be derived from std::exception
They do, it just wasn't explicitly stated, and wasn't tested (which allowed one to throw enums by mistake).
If 'e' doesn't derive from std::exception, the code won't compile when BOOST_NO_EXCEPTIONS is defined, and the original purpose of boost::throw_exceptions was precisely to support the case when BOOST_NO_EXCEPTIONS is defined.
So why to define a template in the case BOOST_NO_EXCEPTIONS is not defined? ______________________ Vicente Juan Botet Escribá

----- Original Message ----- From: "Peter Dimov" <pdimov@pdimov.com> To: <boost@lists.boost.org> Sent: Wednesday, September 10, 2008 1:13 PM Subject: Re: [boost] [exception] library update
vicente.botet:
So why to define a template in the case BOOST_NO_EXCEPTIONS is not defined?
Try to define it as a non-template and see what happens.
OK, I see, a runtime error. So why not let define the user the template when BOOST_NO_EXCEPTIONS is defined. omething like #ifdef BOOST_NO_EXCEPTIONS #ifdef BOOST_NO_EXCEPTIONS_USER_SLOT #include BOOST_NO_EXCEPTIONS_USER_SLOT #endif // BOOST_NO_EXCEPTIONS_USER_SLOT void throw_exception(std::exception const & e); #else // BOOST_NO_EXCEPTIONS template<class E> void throw_exception(E const & e) { throw e; } #endif // BOOST_NO_EXCEPTIONS Vicente

On Mon, Sep 8, 2008 at 2:59 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
I've finished a major refactoring of the Exception library:
[snip]
2) I would like to thank Dave and Robert for complaining about the added weight to boost/throw_exception.hpp. I managed to reduce that cost to less than 400 lines total, all contained in boost/exception/exception.hpp which now does not #include anything (not even standard headers.) If there are more concerns about this issue, let's discuss them now.
Maybe you could add a throw_exception to the subject to attract more readers to the thread?
The latest documentation can be viewed at http://svn.boost.org/svn/boost/trunk/libs/exception/doc/boost-exception.html.
Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
Regards, -- Felipe Magno de Almeida

on Mon Sep 08 2008, "Emil Dotchevski" <emil-AT-revergestudios.com> wrote:
I've finished a major refactoring of the Exception library:
1) Thanks to Peter Dimov's boost/detail/sp_typeinfo.hpp, it now works with or without RTTI support.
2) I would like to thank Dave and Robert for complaining about the added weight to boost/throw_exception.hpp.
My pleasure. Any time you need someone to complain about something, you can call on me ;-)
I managed to reduce that cost to less than 400 lines total, all contained in boost/exception/exception.hpp which now does not #include anything (not even standard headers.)
Wow! That sounds like a major improvement. Robert, do you think you can go back to using BOOST_THROW_EXCEPTION or whatever it was that you dropped because of the weight? -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (5)
-
David Abrahams
-
Emil Dotchevski
-
Felipe Magno de Almeida
-
Peter Dimov
-
vicente.botet