From 0c9d70964e1792a50fdd4174ec75a3db2b6df5b1 Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Fri, 29 Aug 2008 04:56:02 +0000 Subject: [PATCH] enable_current_exception.hpp decoupled from atomic_count.hpp [SVN r48439] --- doc/source/boost-exception.reno | 340 +++++++++--------- .../boost/exception/detail/cloning_base.hpp | 9 +- .../exception/enable_current_exception.hpp | 108 +++--- include/boost/exception_ptr.hpp | 93 ++++- test/cloning_test.cpp | 224 +++++++++++- 5 files changed, 535 insertions(+), 239 deletions(-) diff --git a/doc/source/boost-exception.reno b/doc/source/boost-exception.reno index 671893b..9d42405 100644 --- a/doc/source/boost-exception.reno +++ b/doc/source/boost-exception.reno @@ -54,14 +54,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 156B870761DB092CE4269C1173B479A344A1041BA2B883765AF19A72B371D776 3239976720 117 - 4756 + 6700 @@ -152,14 +152,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 - ED09F845070FF7D381BE5EFB6B55313FD09FBA16B64B69992410380EFA45519C - 2051939590 - 78 - 433 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 + AB48477C625A1E68BF74B055D380697B5761C4DBA41F8B2148F6A0F8A2BAC38E + 3683655261 + 81 + 1480 @@ -250,10 +250,10 @@ 1 - 06FF83AB627CF01DE016240E3664241F90A142A3963F0EAFAE55E4A11742D7FC - 3393983433 - 3433 - 227 + 59EC111578A82535A1DC3EDB486F029664F751D86C2C90D0D3FE0BAFAA87387E + 3274250395 + 3418 + 323 @@ -295,9 +295,9 @@ 1 - 208AD3E1D28FC8033210811C4E44D738A41F0B0B7F747467413A685125A50544 - 2712565394 - 5087 + F052D2548BCDFFFA0DA6CB0AC3731B15EBE7E34F357A4485F0FCD205457859CA + 175131392 + 7021 323 @@ -749,14 +749,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 F87D7E0321BDDAE23D5A6667CB12116411468AEC54E3B35FB9C8CA94BFECA41E 1149388739 296 - 4458 + 6402 @@ -1161,14 +1161,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 - 9DEEF8ED70BF74F501A96BA5DE5BFD42FAD16DE333ABE189E512C332586FC465 - 2250569940 - 1893 - 2563 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 + 5B9A60CD7925F05B8F4A0A8F690EC320226187C26D9D6DD9F3A7793C74A9F4FC + 3344368450 + 1912 + 4488 @@ -1545,14 +1545,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 A098B6FA5BC8E72E0E69C0323195FCC142AE807564C6892FCBD88588F2FBE049 2579522516 405 - 26 + 1563 @@ -1594,14 +1594,14 @@ 2 - BC2FB1723D280E870C34C192CB356C520C5C1C23EA5C209797F5DE3F15758F24 - 997637066 - 3154 - 506 + 3A4D0506DEDA25E46C6F3B3936898F829C428AF153A7B1B5391B02ABA4C0AD0D + 1800726291 + 3277 + 464 DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9 1137981799 192 - 2956 + 3079 @@ -7787,6 +7787,34 @@ -39 + + + + + 2 + 3A4D0506DEDA25E46C6F3B3936898F829C428AF153A7B1B5391B02ABA4C0AD0D + 1800726291 + 3277 + 464 + DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9 + 1137981799 + 192 + 3079 + + + + + + 0 + ../../../../boost/exception/enable_current_exception.hpp + 0 + 0 + + + + -38 + + @@ -7840,42 +7868,14 @@ 2 - BC2FB1723D280E870C34C192CB356C520C5C1C23EA5C209797F5DE3F15758F24 - 997637066 - 3154 - 506 - DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9 - 1137981799 - 192 - 2956 - - - - - - 0 - ../../../../boost/exception/enable_current_exception.hpp - 0 - 0 - - - - -38 - - - - - - - 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 F87D7E0321BDDAE23D5A6667CB12116411468AEC54E3B35FB9C8CA94BFECA41E 1149388739 296 - 4458 + 6402 @@ -7896,14 +7896,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 A098B6FA5BC8E72E0E69C0323195FCC142AE807564C6892FCBD88588F2FBE049 2579522516 405 - 26 + 1563 @@ -7924,42 +7924,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 - 9DEEF8ED70BF74F501A96BA5DE5BFD42FAD16DE333ABE189E512C332586FC465 - 2250569940 - 1893 - 2563 - - - - - - 0 - ../../../../boost/exception_ptr.hpp - 0 - 0 - - - - -29 - - - - - - - 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 156B870761DB092CE4269C1173B479A344A1041BA2B883765AF19A72B371D776 3239976720 117 - 4756 + 6700 @@ -7980,14 +7952,14 @@ 2 - 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F - 3547540308 - 4879 - 531 - ED09F845070FF7D381BE5EFB6B55313FD09FBA16B64B69992410380EFA45519C - 2051939590 - 78 - 433 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 + AB48477C625A1E68BF74B055D380697B5761C4DBA41F8B2148F6A0F8A2BAC38E + 3683655261 + 81 + 1480 @@ -8003,6 +7975,34 @@ -7 + + + + + 2 + 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029 + 3649242015 + 6823 + 521 + 5B9A60CD7925F05B8F4A0A8F690EC320226187C26D9D6DD9F3A7793C74A9F4FC + 3344368450 + 1912 + 4488 + + + + + + 0 + ../../../../boost/exception_ptr.hpp + 0 + 0 + + + + -29 + + @@ -8075,30 +8075,6 @@ -21 - - - - - 1 - 208AD3E1D28FC8033210811C4E44D738A41F0B0B7F747467413A685125A50544 - 2712565394 - 5087 - 323 - - - - - - 0 - ../../../../boost/exception_ptr.hpp - 0 - 0 - - - - -10 - - @@ -8431,6 +8407,30 @@ -40 + + + + + 1 + 59EC111578A82535A1DC3EDB486F029664F751D86C2C90D0D3FE0BAFAA87387E + 3274250395 + 3418 + 323 + + + + + + 0 + ../../../../boost/exception/enable_current_exception.hpp + 0 + 0 + + + + -9 + + @@ -8531,6 +8531,30 @@ -35 + + + + + 1 + F052D2548BCDFFFA0DA6CB0AC3731B15EBE7E34F357A4485F0FCD205457859CA + 175131392 + 7021 + 323 + + + + + + 0 + ../../../../boost/exception_ptr.hpp + 0 + 0 + + + + -10 + + @@ -8711,30 +8735,6 @@ -19 - - - - - 1 - 06FF83AB627CF01DE016240E3664241F90A142A3963F0EAFAE55E4A11742D7FC - 3393983433 - 3433 - 227 - - - - - - 0 - ../../../../boost/exception/enable_current_exception.hpp - 0 - 0 - - - - -9 - - diff --git a/include/boost/exception/detail/cloning_base.hpp b/include/boost/exception/detail/cloning_base.hpp index 5e5ff66..ad423fe 100644 --- a/include/boost/exception/detail/cloning_base.hpp +++ b/include/boost/exception/detail/cloning_base.hpp @@ -16,12 +16,19 @@ boost { class clone_base; + struct + new_clone + { + clone_base const * c_; + void (*d_)(clone_base const *); + }; + class cloning_base { public: - virtual clone_base const * clone() const = 0; + virtual new_clone clone() const = 0; protected: diff --git a/include/boost/exception/enable_current_exception.hpp b/include/boost/exception/enable_current_exception.hpp index d350b4d..f39234e 100644 --- a/include/boost/exception/enable_current_exception.hpp +++ b/include/boost/exception/enable_current_exception.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -31,39 +30,8 @@ boost { } - class - clone_base: - public counted_base - { - public: - - virtual void rethrow() const=0; - }; - - struct - bad_alloc_impl: - public clone_base, - public std::bad_alloc - { - void - add_ref() const - { - } - - void - release() const - { - } - - void - rethrow() const - { - throw *this; - } - }; - template - clone_base * make_clone( T const & ); + new_clone make_clone( T const & ); template class @@ -80,15 +48,46 @@ boost copy_boost_exception(this,&x); } + ~clone_impl() throw() + { + } + private: - clone_base const * + new_clone clone() const { return make_clone(*this); } }; + class + clone_base + { + public: + + virtual void rethrow() const=0; + virtual ~clone_base() throw()=0; + }; + + inline + clone_base:: + ~clone_base() throw() + { + } + + struct + bad_alloc_impl: + public clone_base, + public std::bad_alloc + { + void + rethrow() const + { + throw *this; + } + }; + template class exception_clone: @@ -99,27 +98,15 @@ boost explicit exception_clone( T const & x ): - T(x), - count_(0) + T(x) { copy_boost_exception(this,&x); } private: - mutable detail::atomic_count count_; - - void - add_ref() const + ~exception_clone() throw() { - ++count_; - } - - void - release() const - { - if( !--count_ ) - delete this; } void @@ -129,27 +116,44 @@ boost } }; + inline + void + delete_clone( clone_base const * c ) + { + BOOST_ASSERT(c!=0); + delete c; + } + + inline + void + delete_clone_noop( clone_base const * ) + { + } + template inline - clone_base * + new_clone make_clone( T const & x ) { + new_clone tmp = {0,0}; try { - return new exception_clone(x); + tmp.c_=new exception_clone(x); + tmp.d_=&delete_clone; } catch( std::bad_alloc & ) { static bad_alloc_impl bad_alloc; - return &bad_alloc; + tmp.c_=&bad_alloc; + tmp.d_=&delete_clone_noop; } catch( ... ) { BOOST_ASSERT(0); - return 0; } + return tmp; } } diff --git a/include/boost/exception_ptr.hpp b/include/boost/exception_ptr.hpp index cb1d73e..94330fd 100644 --- a/include/boost/exception_ptr.hpp +++ b/include/boost/exception_ptr.hpp @@ -8,13 +8,76 @@ #include #include -#include +#include #include #include namespace boost { + namespace + exception_detail + { + class + counted_clone: + public counted_base + { + public: + + counted_clone(): + count_(0), + clone_(0) + { + } + + void + set( new_clone const & nc ) + { + clone_ = nc.c_; + clone_deleter_ = nc.d_; + BOOST_ASSERT(clone_!=0); + BOOST_ASSERT(clone_deleter_!=0); + } + + void + rethrow() const + { + BOOST_ASSERT(clone_!=0); + clone_->rethrow(); + } + + private: + + counted_clone( counted_clone const & ); + counted_clone & operator=( counted_clone const & ); + + mutable detail::atomic_count count_; + clone_base const * clone_; + void (*clone_deleter_)(clone_base const *); + + ~counted_clone() throw() + { + if( clone_ ) + clone_deleter_(clone_); + } + + void + add_ref() const + { + ++count_; + } + + void + release() const + { + if( !--count_ ) + delete this; + } + }; + } + + typedef intrusive_ptr exception_ptr; + class unknown_exception: public exception, @@ -37,8 +100,6 @@ boost } }; - typedef intrusive_ptr exception_ptr; - namespace exception_detail { @@ -72,17 +133,21 @@ boost exception_ptr current_exception_std_exception( T const & e1 ) { + intrusive_ptr x(new exception_detail::counted_clone); if( boost::exception const * e2 = get_boost_exception(&e1) ) - return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2))); + x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2))); else - return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1))); + x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1))); + return x; } inline exception_ptr current_exception_unknown_exception() { - return exception_ptr(exception_detail::make_clone(unknown_exception())); + intrusive_ptr x(new exception_detail::counted_clone); + x->set(exception_detail::make_clone(unknown_exception())); + return x; } inline @@ -90,7 +155,11 @@ boost current_exception_unknown_std_exception( std::exception const & e ) { if( boost::exception const * be = get_boost_exception(&e) ) - return exception_ptr(exception_detail::make_clone(unknown_exception(*be))); + { + intrusive_ptr x(new exception_detail::counted_clone); + x->set(exception_detail::make_clone(unknown_exception(*be))); + return x; + } else return current_exception_unknown_exception(); } @@ -99,7 +168,9 @@ boost exception_ptr current_exception_unknown_boost_exception( boost::exception const & e ) { - return exception_ptr(exception_detail::make_clone(unknown_exception(e))); + intrusive_ptr x(new exception_detail::counted_clone); + x->set(exception_detail::make_clone(unknown_exception(e))); + return x; } } @@ -114,9 +185,9 @@ boost catch( exception_detail::cloning_base & e ) { - exception_detail::clone_base const * c = e.clone(); - BOOST_ASSERT(c!=0); - return exception_ptr(c); + intrusive_ptr x(new exception_detail::counted_clone); + x->set(e.clone()); + return x; } catch( std::invalid_argument & e ) diff --git a/test/cloning_test.cpp b/test/cloning_test.cpp index 5f2319a..62e1de1 100644 --- a/test/cloning_test.cpp +++ b/test/cloning_test.cpp @@ -4,20 +4,63 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include #include +#include + +typedef boost::error_info my_info; struct -test_exception: +derives_nothing + { + int & count; + + explicit + derives_nothing( int & count ): + count(count) + { + ++count; + } + + derives_nothing( derives_nothing const & x ): + count(x.count) + { + ++count; + } + + ~derives_nothing() + { + --count; + } + }; + +struct +derives_std_exception: std::exception { }; -int -main() +struct +derives_std_boost_exception: + std::exception, + boost::exception + { + }; + +struct +derives_boost_exception: + boost::exception + { + }; + +template +void +test_std_exception() { try { - throw boost::enable_current_exception(test_exception()); + throw T(); } catch( ... ) @@ -29,7 +72,7 @@ main() BOOST_TEST(false); } catch( - test_exception & ) + T & ) { } catch( @@ -38,5 +81,176 @@ main() BOOST_TEST(false); } } + } + +template +void +test_std_exception_what() + { + try + { + throw T("what"); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + T & x ) + { + BOOST_TEST(std::string("what")==x.what()); + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + } + +int +main() + { + int count=0; + try + { + throw boost::enable_current_exception(derives_nothing(count)); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + derives_nothing & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + BOOST_TEST(count==0); + + try + { + throw boost::enable_current_exception(derives_std_exception()); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + derives_std_exception & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + + try + { + throw derives_std_exception(); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + boost::unknown_exception & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + + test_std_exception_what(); + test_std_exception_what(); + test_std_exception_what(); + test_std_exception(); + test_std_exception(); + test_std_exception(); + test_std_exception(); + + try + { + throw derives_std_boost_exception() << my_info(42); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + boost::unknown_exception & x ) + { + BOOST_TEST(boost::get_error_info(x)); + if( boost::shared_ptr p=boost::get_error_info(x) ) + BOOST_TEST(*p==42); + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + + try + { + throw derives_boost_exception() << my_info(42); + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + boost::unknown_exception & x ) + { + BOOST_TEST(boost::get_error_info(x)); + if( boost::shared_ptr p=boost::get_error_info(x) ) + BOOST_TEST(*p==42); + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + return boost::report_errors(); }