From 5258fbc2d1610ae6ab89405608795032c81ff6ae Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Fri, 29 Aug 2008 19:27:38 +0000 Subject: [PATCH] Further simplified enable_current_exception. Improved exception_ptr testing. [SVN r48455] --- .../boost/exception/detail/cloning_base.hpp | 48 --- .../exception/enable_current_exception.hpp | 117 ++----- include/boost/exception_ptr.hpp | 286 +++++++++++++----- test/cloning_test.cpp | 208 +++++++++++++ 4 files changed, 441 insertions(+), 218 deletions(-) delete mode 100644 include/boost/exception/detail/cloning_base.hpp diff --git a/include/boost/exception/detail/cloning_base.hpp b/include/boost/exception/detail/cloning_base.hpp deleted file mode 100644 index ad423fe..0000000 --- a/include/boost/exception/detail/cloning_base.hpp +++ /dev/null @@ -1,48 +0,0 @@ -//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. - -//Distributed under the Boost Software License, Version 1.0. (See accompanying -//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef UUID_F7D5662CCB0F11DCA353CAC656D89593 -#define UUID_F7D5662CCB0F11DCA353CAC656D89593 - -#include - -namespace -boost - { - namespace - exception_detail - { - class clone_base; - - struct - new_clone - { - clone_base const * c_; - void (*d_)(clone_base const *); - }; - - class - cloning_base - { - public: - - virtual new_clone clone() const = 0; - - protected: - -#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) -virtual //Disable bogus GCC warning. -#endif -#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) -virtual //Disable bogus msvc warning. -#endif - ~cloning_base() throw() - { - } - }; - } - } - -#endif diff --git a/include/boost/exception/enable_current_exception.hpp b/include/boost/exception/enable_current_exception.hpp index f39234e..5b277d3 100644 --- a/include/boost/exception/enable_current_exception.hpp +++ b/include/boost/exception/enable_current_exception.hpp @@ -7,9 +7,6 @@ #define UUID_78CC85B2914F11DC8F47B48E55D89593 #include -#include -#include -#include namespace boost @@ -17,6 +14,22 @@ boost namespace exception_detail { + class + clone_base + { + public: + + virtual clone_base const * clone() const = 0; + virtual void rethrow() const = 0; + virtual ~clone_base() throw() = 0; + }; + + inline + clone_base:: + ~clone_base() throw() + { + } + inline void copy_boost_exception( exception * a, exception const * b ) @@ -30,14 +43,11 @@ boost { } - template - new_clone make_clone( T const & ); - template class clone_impl: public T, - public cloning_base + public clone_base { public: @@ -54,107 +64,18 @@ boost private: - new_clone + clone_base const * clone() const { - return make_clone(*this); + return new clone_impl(*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: - public T, - public clone_base - { - public: - - explicit - exception_clone( T const & x ): - T(x) - { - copy_boost_exception(this,&x); - } - - private: - - ~exception_clone() throw() - { - } - - void - rethrow() const - { - throw clone_impl(*this); - } - }; - - inline - void - delete_clone( clone_base const * c ) - { - BOOST_ASSERT(c!=0); - delete c; - } - - inline - void - delete_clone_noop( clone_base const * ) - { - } - - template - inline - new_clone - make_clone( T const & x ) - { - new_clone tmp = {0,0}; - try - { - tmp.c_=new exception_clone(x); - tmp.d_=&delete_clone; - } - catch( - std::bad_alloc & ) - { - static bad_alloc_impl bad_alloc; - tmp.c_=&bad_alloc; - tmp.d_=&delete_clone_noop; - } - catch( - ... ) - { - BOOST_ASSERT(0); - } - return tmp; - } } template diff --git a/include/boost/exception_ptr.hpp b/include/boost/exception_ptr.hpp index 94330fd..fad6002 100644 --- a/include/boost/exception_ptr.hpp +++ b/include/boost/exception_ptr.hpp @@ -6,8 +6,8 @@ #ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593 #define UUID_FA5836A2CADA11DC8CD47C8555D89593 -#include #include +#include #include #include #include @@ -31,19 +31,19 @@ boost } void - set( new_clone const & nc ) + set( clone_base const * c ) { - clone_ = nc.c_; - clone_deleter_ = nc.d_; + clone_ = c; BOOST_ASSERT(clone_!=0); - BOOST_ASSERT(clone_deleter_!=0); } void rethrow() const { - BOOST_ASSERT(clone_!=0); - clone_->rethrow(); + if( clone_ ) + clone_->rethrow(); + else + throw enable_current_exception(std::bad_alloc()); } private: @@ -58,7 +58,7 @@ boost ~counted_clone() throw() { if( clone_ ) - clone_deleter_(clone_); + delete clone_; } void @@ -74,14 +74,114 @@ boost delete this; } }; + + struct + bad_alloc_tag + { + }; + + struct + bad_exception_tag + { + }; } - typedef intrusive_ptr exception_ptr; + class exception_ptr; + void rethrow_exception( exception_ptr const & ); + + class + exception_ptr + { + private: + + friend void rethrow_exception( exception_ptr const & ); + + enum + { + bad_alloc_caught, + clone_failed, + ok + } what_happened_; + + intrusive_ptr c_; + + void + rethrow() const + { + switch( + what_happened_ ) + { + case + bad_alloc_caught: + throw enable_current_exception(std::bad_alloc()); + case + clone_failed: + throw enable_current_exception(std::bad_exception()); + case + ok: + BOOST_ASSERT(c_.get()!=0); + c_->rethrow(); + } + BOOST_ASSERT(0); + } + + typedef intrusive_ptr exception_ptr::*unspecified_bool_type; + + public: + + explicit + exception_ptr( exception_detail::bad_alloc_tag ): + what_happened_(bad_alloc_caught) + { + } + + explicit + exception_ptr( exception_detail::bad_exception_tag ): + what_happened_(clone_failed) + { + } + + exception_ptr(): + what_happened_(ok) + { + } + + explicit + exception_ptr( intrusive_ptr const & c ): + what_happened_(ok), + c_(c) + { + BOOST_ASSERT(c_.get()!=0); + } + + friend + bool + operator==( exception_ptr const & a, exception_ptr const & b ) + { + return + a.what_happened_==ok && + b.what_happened_==ok && + a.c_==b.c_; + } + + friend + bool + operator!=( exception_ptr const & a, exception_ptr const & b ) + { + return !(a==b); + } + + operator unspecified_bool_type() const + { + return (what_happened_!=ok || c_) ? &exception_ptr::c_ : 0; + } + }; class unknown_exception: public exception, - public std::exception + public std::exception, + public exception_detail::clone_base { public: @@ -98,6 +198,20 @@ boost ~unknown_exception() throw() { } + + private: + + clone_base const * + clone() const + { + return new unknown_exception(*this); + } + + void + rethrow() const + { + throw *this; + } }; namespace @@ -107,7 +221,8 @@ boost class current_exception_std_exception_wrapper: public T, - public boost::exception + public boost::exception, + public clone_base { public: @@ -126,6 +241,20 @@ boost ~current_exception_std_exception_wrapper() throw() { } + + private: + + clone_base const * + clone() const + { + return new current_exception_std_exception_wrapper(*this); + } + + void + rethrow() const + { + throw *this; + } }; template @@ -135,10 +264,10 @@ boost { intrusive_ptr x(new exception_detail::counted_clone); if( boost::exception const * e2 = get_boost_exception(&e1) ) - x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2))); + x->set(new current_exception_std_exception_wrapper(e1,*e2)); else - x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1))); - return x; + x->set(new current_exception_std_exception_wrapper(e1)); + return exception_ptr(x); } inline @@ -146,8 +275,8 @@ boost current_exception_unknown_exception() { intrusive_ptr x(new exception_detail::counted_clone); - x->set(exception_detail::make_clone(unknown_exception())); - return x; + x->set(new unknown_exception()); + return exception_ptr(x); } inline @@ -157,8 +286,8 @@ boost if( boost::exception const * be = get_boost_exception(&e) ) { intrusive_ptr x(new exception_detail::counted_clone); - x->set(exception_detail::make_clone(unknown_exception(*be))); - return x; + x->set(new unknown_exception(*be)); + return exception_ptr(x); } else return current_exception_unknown_exception(); @@ -169,8 +298,8 @@ boost current_exception_unknown_boost_exception( boost::exception const & e ) { intrusive_ptr x(new exception_detail::counted_clone); - x->set(exception_detail::make_clone(unknown_exception(e))); - return x; + x->set(new unknown_exception(e)); + return exception_ptr(x); } } @@ -180,64 +309,77 @@ boost { try { - throw; + try + { + throw; + } + catch( + exception_detail::clone_base & e ) + { + intrusive_ptr x(new exception_detail::counted_clone); + x->set(e.clone()); + return exception_ptr(x); + } + catch( + std::invalid_argument & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::out_of_range & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::logic_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_alloc & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_cast & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_typeid & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_exception & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::exception & e ) + { + return exception_detail::current_exception_unknown_std_exception(e); + } + catch( + boost::exception & e ) + { + return exception_detail::current_exception_unknown_boost_exception(e); + } + catch( + ... ) + { + return exception_detail::current_exception_unknown_exception(); + } } catch( - exception_detail::cloning_base & e ) + std::bad_alloc & ) { - intrusive_ptr x(new exception_detail::counted_clone); - x->set(e.clone()); - return x; - } - catch( - std::invalid_argument & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::out_of_range & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::logic_error & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::bad_alloc & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::bad_cast & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::bad_typeid & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::bad_exception & e ) - { - return exception_detail::current_exception_std_exception(e); - } - catch( - std::exception & e ) - { - return exception_detail::current_exception_unknown_std_exception(e); - } - catch( - boost::exception & e ) - { - return exception_detail::current_exception_unknown_boost_exception(e); + return exception_ptr( exception_detail::bad_alloc_tag() ); } catch( ... ) { - return exception_detail::current_exception_unknown_exception(); + return exception_ptr( exception_detail::bad_exception_tag() ); } } @@ -260,7 +402,7 @@ boost void rethrow_exception( exception_ptr const & p ) { - p->rethrow(); + p.rethrow(); } } diff --git a/test/cloning_test.cpp b/test/cloning_test.cpp index 62e1de1..a6146d6 100644 --- a/test/cloning_test.cpp +++ b/test/cloning_test.cpp @@ -11,6 +11,25 @@ typedef boost::error_info my_info; +template +struct +may_throw_on_copy + { + may_throw_on_copy(): + throw_(false) + { + } + + may_throw_on_copy( may_throw_on_copy const & x ): + throw_(x.throw_) + { + if( throw_ ) + throw T(); + } + + bool throw_; + }; + struct derives_nothing { @@ -66,6 +85,9 @@ test_std_exception() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -74,6 +96,24 @@ test_std_exception() catch( T & ) { + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + T & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } } catch( ... ) @@ -95,6 +135,9 @@ test_std_exception_what() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -104,6 +147,89 @@ test_std_exception_what() T & x ) { BOOST_TEST(std::string("what")==x.what()); + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + T & x ) + { + BOOST_TEST(std::string("what")==x.what()); + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + } + +template +void +test_throw_on_copy() + { + try + { + try + { + throw boost::enable_current_exception(may_throw_on_copy()); + } + catch( + may_throw_on_copy & x ) + { + x.throw_=true; + throw; + } + catch( + ... ) + { + BOOST_TEST(false); + } + } + catch( + ... ) + { + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + Catch & ) + { + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + try + { + boost::rethrow_exception(p); + BOOST_TEST(false); + } + catch( + Catch & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } } catch( ... ) @@ -116,6 +242,10 @@ test_std_exception_what() int main() { + BOOST_TEST( boost::exception_ptr()==boost::exception_ptr() ); + BOOST_TEST( !(boost::exception_ptr()!=boost::exception_ptr()) ); + BOOST_TEST( !boost::exception_ptr() ); + int count=0; try { @@ -125,6 +255,9 @@ main() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -150,6 +283,9 @@ main() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -158,6 +294,24 @@ main() catch( derives_std_exception & ) { + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + try + { + rethrow_exception(p); + BOOST_TEST(false); + } + catch( + derives_std_exception & ) + { + } + catch( + ... ) + { + BOOST_TEST(false); + } } catch( ... ) @@ -174,6 +328,9 @@ main() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -206,6 +363,9 @@ main() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -217,6 +377,27 @@ main() BOOST_TEST(boost::get_error_info(x)); if( boost::shared_ptr p=boost::get_error_info(x) ) BOOST_TEST(*p==42); + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + 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); + } } catch( ... ) @@ -233,6 +414,9 @@ main() ... ) { boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); try { rethrow_exception(p); @@ -244,6 +428,27 @@ main() BOOST_TEST(boost::get_error_info(x)); if( boost::shared_ptr p=boost::get_error_info(x) ) BOOST_TEST(*p==42); + boost::exception_ptr p = boost::current_exception(); + BOOST_TEST(!(p==boost::exception_ptr())); + BOOST_TEST(p!=boost::exception_ptr()); + BOOST_TEST(p); + 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); + } } catch( ... ) @@ -252,5 +457,8 @@ main() } } + test_throw_on_copy(); + test_throw_on_copy(); + return boost::report_errors(); }