diff --git a/include/boost/exception/detail/counted_base.hpp b/include/boost/exception/detail/counted_base.hpp index 7a81885..d9f12d1 100644 --- a/include/boost/exception/detail/counted_base.hpp +++ b/include/boost/exception/detail/counted_base.hpp @@ -6,8 +6,6 @@ #ifndef UUID_DBA0D90C930911DCBA7B675A56D89593 #define UUID_DBA0D90C930911DCBA7B675A56D89593 -#include - namespace boost { @@ -36,12 +34,7 @@ boost 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 + virtual ~counted_base() throw() { } diff --git a/include/boost/exception/detail/refcount_ptr.hpp b/include/boost/exception/detail/refcount_ptr.hpp new file mode 100644 index 0000000..0c16292 --- /dev/null +++ b/include/boost/exception/detail/refcount_ptr.hpp @@ -0,0 +1,79 @@ +//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_490EADC876F011DDA2F00A4756D89593 +#define UUID_490EADC876F011DDA2F00A4756D89593 + +namespace +boost + { + namespace + exception_detail + { + template + class + refcount_ptr + { + public: + + refcount_ptr(): + px_(0) + { + } + + ~refcount_ptr() + { + release(); + } + + refcount_ptr( refcount_ptr const & x ): + px_(x.px_) + { + add_ref(); + } + + refcount_ptr & + operator=( refcount_ptr const & x ) + { + adopt(x.px_); + return *this; + } + + void + adopt( T * px ) + { + release(); + px_=px; + add_ref(); + } + + T * + get() const + { + return px_; + } + + private: + + T * px_; + + void + add_ref() + { + if( px_ ) + intrusive_ptr_add_ref(px_); + } + + void + release() + { + if( px_ ) + intrusive_ptr_release(px_); + } + }; + } + } + +#endif diff --git a/include/boost/exception/enable_error_info.hpp b/include/boost/exception/enable_error_info.hpp index 4b8effd..8029313 100644 --- a/include/boost/exception/enable_error_info.hpp +++ b/include/boost/exception/enable_error_info.hpp @@ -7,8 +7,6 @@ #define UUID_0C5D492E909711DCB658AD4556D89593 #include -#include -#include #include namespace @@ -57,43 +55,21 @@ boost typedef error_info_injector type; }; -#if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) - template - struct - sizeof_dispatch - { - BOOST_STATIC_CONSTANT(int, value = sizeof(dispatch((T*)0)) ); - }; - - template - struct - enable_error_info_return_type - { - typedef typename enable_error_info_helper::value>::type type; - }; -#else template struct enable_error_info_return_type { typedef typename enable_error_info_helper::type type; }; -#endif } template inline -#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) typename -#endif exception_detail::enable_error_info_return_type::type enable_error_info( T const & x ) { - return -#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) - typename -#endif - exception_detail::enable_error_info_return_type::type(x); + return typename exception_detail::enable_error_info_return_type::type(x); } } diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp index b3a754d..5a15480 100644 --- a/include/boost/exception/exception.hpp +++ b/include/boost/exception/exception.hpp @@ -7,7 +7,7 @@ #define UUID_274DA366004E11DCB1DDFE2E56D89593 #include -#include +#include namespace boost @@ -61,28 +61,16 @@ boost { } -#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) - //Force class exception to be abstract. - //Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected. virtual ~exception() throw()=0; -#else -#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) - virtual //Disable bogus GCC warning. -#endif - ~exception() throw() - { - } -#endif char const * _diagnostic_information() const throw() { - if( data_ ) + if( exception_detail::error_info_container * c=data_.get() ) try { - char const * w = data_->diagnostic_information(); - BOOST_ASSERT(w!=0); - return w; + if( char const * w = c->diagnostic_information() ) + return w; } catch(...) { @@ -97,16 +85,14 @@ boost template friend shared_ptr exception_detail::get_data( exception const & ); - mutable intrusive_ptr data_; + mutable exception_detail::refcount_ptr data_; }; -#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) //See above. inline exception:: ~exception() throw() { } -#endif } #endif diff --git a/include/boost/exception/get_error_info.hpp b/include/boost/exception/get_error_info.hpp index e512737..1c4a030 100644 --- a/include/boost/exception/get_error_info.hpp +++ b/include/boost/exception/get_error_info.hpp @@ -22,8 +22,8 @@ boost shared_ptr get_data( exception const & x ) { - if( x.data_ ) - if( shared_ptr eib = x.data_->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) ) + if( exception_detail::error_info_container * c=x.data_.get() ) + if( shared_ptr eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) ) { #ifndef BOOST_NO_RTTI BOOST_ASSERT( 0!=dynamic_cast(eib.get()) ); diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp index 1a4b33d..a5808da 100644 --- a/include/boost/exception/info.hpp +++ b/include/boost/exception/info.hpp @@ -126,7 +126,7 @@ boost private: - friend class boost::exception; + friend class boost::exception; typedef std::map< type_info_, shared_ptr > error_info_map; error_info_map info_; @@ -151,9 +151,10 @@ boost void set_data( exception const * e, shared_ptr const & x, exception_detail::type_info_ const & typeid_ ) { - if( !e->data_ ) - e->data_ = intrusive_ptr(new exception_detail::error_info_container_impl); - e->data_->set(x,typeid_); + exception_detail::error_info_container * c; + if( !(c=e->data_.get()) ) + e->data_.adopt(c=new exception_detail::error_info_container_impl); + c->set(x,typeid_); } } diff --git a/include/boost/exception_ptr.hpp b/include/boost/exception_ptr.hpp index 088e5b6..6462a80 100644 --- a/include/boost/exception_ptr.hpp +++ b/include/boost/exception_ptr.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d3463a6..a3f1348 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -29,6 +29,7 @@ run throw_exception_test.cpp helper2.cpp ; run errno_test.cpp ; run error_info_test.cpp ; run diagnostic_information_test.cpp ; +run refcount_ptr_test.cpp ; compile-fail exception_fail.cpp ; compile-fail throw_exception_fail.cpp ; diff --git a/test/refcount_ptr_test.cpp b/test/refcount_ptr_test.cpp new file mode 100644 index 0000000..769e6a2 --- /dev/null +++ b/test/refcount_ptr_test.cpp @@ -0,0 +1,105 @@ +//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) + +#include +#include + +struct +test_type + { + test_type( int & count ): + count_(count) + { + BOOST_TEST(count_==42); + count_=0; + } + + ~test_type() + { + BOOST_TEST(!count_); + count_=42; + } + + friend + void + intrusive_ptr_add_ref( test_type const * c ) + { + ++c->count_; + } + + friend + void + intrusive_ptr_release( test_type const * c ) + { + if( !--c->count_ ) + delete c; + } + + private: + + test_type( test_type const & ); + test_type & operator=( test_type const & ); + + mutable int & count_; + }; + +int +main() + { + using boost::exception_detail::refcount_ptr; + + { + refcount_ptr x; + BOOST_TEST(!x.get()); + } + + { + int count=42; + test_type * a=new test_type(count); + BOOST_TEST(!count); + { + refcount_ptr p; + BOOST_TEST(0==count); + p.adopt(a); + BOOST_TEST(p.get()==a); + BOOST_TEST(1==count); + { + refcount_ptr q; + q.adopt(p.get()); + BOOST_TEST(q.get()==a); + BOOST_TEST(2==count); + { + refcount_ptr t(p); + BOOST_TEST(t.get()==a); + BOOST_TEST(3==count); + { + refcount_ptr n; + n=t; + BOOST_TEST(n.get()==a); + BOOST_TEST(4==count); + int cb=42; + test_type * b=new test_type(cb); + BOOST_TEST(0==cb); + n.adopt(b); + BOOST_TEST(1==cb); + BOOST_TEST(n.get()==b); + BOOST_TEST(3==count); + n.adopt(0); + BOOST_TEST(42==cb); + } + BOOST_TEST(t.get()==a); + BOOST_TEST(3==count); + } + BOOST_TEST(q.get()==a); + BOOST_TEST(2==count); + } + BOOST_TEST(p.get()==a); + BOOST_TEST(1==count); + } + BOOST_TEST(42==count); + } + + return boost::report_errors(); + }