boost/exception/enable_current_exception.hpp
//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_78CC85B2914F11DC8F47B48E55D89593 #define UUID_78CC85B2914F11DC8F47B48E55D89593 #include <boost/exception/exception.hpp> #include <boost/exception/detail/cloning_base.hpp> #include <boost/detail/atomic_count.hpp> #include <boost/assert.hpp> #include <new> namespace boost { namespace exception_detail { 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 <class T> clone_base * make_clone( T const & ); template <class T> class clone_impl: public T, public cloning_base { public: explicit clone_impl( T const & x ): T(x) { if( boost::exception * be1=dynamic_cast<boost::exception *>(this) ) if( boost::exception const * be2=dynamic_cast<boost::exception const *>(&x) ) *be1 = *be2; } private: clone_base const * clone() const { return make_clone<T>(*this); } }; template <class T> class exception_clone: public T, public clone_base { public: explicit exception_clone( T const & x ): T(x), count_(0) { if( boost::exception * be1=dynamic_cast<boost::exception *>(this) ) if( boost::exception const * be2=dynamic_cast<boost::exception const *>(&x) ) *be1 = *be2; } private: detail::atomic_count mutable count_; void add_ref() const { ++count_; } void release() const { if( !--count_ ) delete this; } void rethrow() const { throw clone_impl<T>(*this); } }; template <class T> inline clone_base * make_clone( T const & x ) { try { return new exception_clone<T>(x); } catch( std::bad_alloc & ) { static bad_alloc_impl bad_alloc; return &bad_alloc; } catch( ... ) { BOOST_ASSERT(0); return 0; } } } template <class T> inline exception_detail::clone_impl<T> enable_current_exception( T const & x ) { return exception_detail::clone_impl<T>(x); } } #endif