Optimization for error_info<throw_function>, error_info<throw_file>, error_info<throw_line>. Refactored exception_ptr to use shared_ptr.

[SVN r48521]
This commit is contained in:
Emil Dotchevski
2008-09-01 21:06:09 +00:00
parent 9a35c999a2
commit b84fb75a60
16 changed files with 418 additions and 455 deletions

View File

@ -66,11 +66,11 @@ my_fopen( char const * name, char const * mode )
if( FILE * f = ::fopen(name,mode) ) if( FILE * f = ::fopen(name,mode) )
return boost::shared_ptr<FILE>(f,fclose); return boost::shared_ptr<FILE>(f,fclose);
else else
throw fopen_error() << BOOST_ERROR_INFO << BOOST_THROW_EXCEPTION(fopen_error() <<
errno_info(errno) << errno_info(errno) <<
file_name_info(name) << file_name_info(name) <<
open_mode_info(mode) << open_mode_info(mode) <<
function_info("fopen"); function_info("fopen"));
} }
void void
@ -78,10 +78,10 @@ my_fread( void * buffer, size_t size, size_t count, boost::shared_ptr<FILE> cons
{ {
assert(stream); assert(stream);
if( count!=fread(buffer,size,count,stream.get()) || ferror(stream.get()) ) if( count!=fread(buffer,size,count,stream.get()) || ferror(stream.get()) )
throw fread_error() << BOOST_ERROR_INFO << BOOST_THROW_EXCEPTION(fread_error() <<
function_info("fread") << function_info("fread") <<
errno_info(errno) << errno_info(errno) <<
file_stream_info(boost::weak_ptr<FILE>(stream)); file_stream_info(boost::weak_ptr<FILE>(stream)));
} }
void void
@ -89,10 +89,10 @@ my_fwrite( void const * buffer, size_t size, size_t count, boost::shared_ptr<FIL
{ {
assert(stream); assert(stream);
if( count!=fwrite(buffer,size,count,stream.get()) || ferror(stream.get()) ) if( count!=fwrite(buffer,size,count,stream.get()) || ferror(stream.get()) )
throw fwrite_error() << BOOST_ERROR_INFO << BOOST_THROW_EXCEPTION(fwrite_error() <<
function_info("fwrite") << function_info("fwrite") <<
errno_info(errno) << errno_info(errno) <<
file_stream_info(boost::weak_ptr<FILE>(stream)); file_stream_info(boost::weak_ptr<FILE>(stream)));
} }
void void

View File

@ -20,6 +20,6 @@ g()
catch( catch(
boost::exception & e ) boost::exception & e )
{ {
std::cerr << e.diagnostic_information(); std::cerr << diagnostic_information(e);
} }
} }

View File

@ -6,7 +6,6 @@
#ifndef UUID_CE6983AC753411DDA764247956D89593 #ifndef UUID_CE6983AC753411DDA764247956D89593
#define UUID_CE6983AC753411DDA764247956D89593 #define UUID_CE6983AC753411DDA764247956D89593
#include <boost/detail/workaround.hpp>
#include <string> #include <string>
namespace namespace
@ -25,10 +24,8 @@ boost
protected: protected:
#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) virtual
virtual //Disable bogus GCC warning. ~error_info_base() throw()
#endif
~error_info_base()
{ {
} }
}; };

View File

@ -8,7 +8,6 @@
#include <boost/exception/detail/type_info.hpp> #include <boost/exception/detail/type_info.hpp>
#include <iomanip> #include <iomanip>
#include <typeinfo>
#include <ios> #include <ios>
#include <string> #include <string>
#include <sstream> #include <sstream>

View File

@ -44,13 +44,6 @@ boost
return a.type_==b.type_; return a.type_==b.type_;
} }
friend
bool
operator!=( type_info_ const & a, type_info_ const & b )
{
return !(a==b);
}
friend friend
bool bool
operator<( type_info_ const & a, type_info_ const & b ) operator<( type_info_ const & a, type_info_ const & b )
@ -88,13 +81,6 @@ boost
return (*a.type_)==(*b.type_); return (*a.type_)==(*b.type_);
} }
friend
bool
operator!=( type_info_ const & a, type_info_ const & b )
{
return !(a==b);
}
friend friend
bool bool
operator<( type_info_ const & a, type_info_ const & b ) operator<( type_info_ const & a, type_info_ const & b )
@ -109,6 +95,13 @@ boost
} }
}; };
#endif #endif
inline
bool
operator!=( type_info_ const & a, type_info_ const & b )
{
return !(a==b);
}
} }
} }

View File

@ -6,9 +6,9 @@
#ifndef UUID_0552D49838DD11DD90146B8956D89593 #ifndef UUID_0552D49838DD11DD90146B8956D89593
#define UUID_0552D49838DD11DD90146B8956D89593 #define UUID_0552D49838DD11DD90146B8956D89593
#include <boost/exception/exception.hpp> #include <boost/exception/get_error_info.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <exception> #include <exception>
#include <sstream>
#include <string> #include <string>
namespace namespace
@ -17,13 +17,27 @@ boost
namespace namespace
exception_detail exception_detail
{ {
char const *
get_diagnostic_information( exception const & x )
{
if( error_info_container * c=x.data_.get() )
try
{
return c->diagnostic_information();
}
catch(...)
{
}
return 0;
}
template <class T> template <class T>
std::string std::string
std_exception_diagnostic_information( std::exception const * x, T const & ) std_exception_diagnostic_information( std::exception const * x, T const & )
{ {
if( char const * s=x->what() ) if( char const * s=x->what() )
if( *s ) if( *s )
return std::string("std::exception::what(): ")+s; return std::string("\nstd::exception::what(): ")+s;
return std::string(); return std::string();
} }
@ -38,55 +52,29 @@ boost
#endif #endif
return std::string(); return std::string();
} }
template <class T>
std::string
boost_exception_diagnostic_information( boost::exception const * x, T const & )
{
if( char const * s=x->diagnostic_information() )
if( *s )
return std::string("boost::exception::diagnostic_information():\n")+s;
return std::string();
} }
template <class T>
std::string
boost_exception_diagnostic_information( void const *, T const & e )
{
#ifndef BOOST_NO_RTTI
if( exception const * x=dynamic_cast<exception const *>(&e) )
return boost_exception_diagnostic_information(x,e);
else
#endif
return std::string();
}
}
template <class T>
inline inline
std::string std::string
diagnostic_information( T const & x ) diagnostic_information( exception const & x )
{ {
std::string di= std::ostringstream tmp;
#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID) tmp <<
std::string("Static exception type: ")+BOOST_EXCEPTION_STATIC_TYPEID(T) "boost::exception diagnostic information:"
#else #if !defined(BOOST_NO_RTTI) && !defined(BOOST_NO_TYPEID)
std::string("Dynamic exception type: ")+BOOST_EXCEPTION_DYNAMIC_TYPEID(x) "\nDynamic exception type: " << BOOST_EXCEPTION_DYNAMIC_TYPEID(x).name()
#endif #endif
.name(); ;
std::string di1=exception_detail::std_exception_diagnostic_information(&x,x); if( boost::shared_ptr<char const * const> f=get_error_info<throw_function>(x) )
if( !di1.empty() ) tmp << "\nThrow function: " << *f;
{ if( boost::shared_ptr<char const * const> f=get_error_info<throw_file>(x) )
di+='\n'; tmp << "\nThrow file name: " << *f;
di+=di1; if( boost::shared_ptr<int const> l=get_error_info<throw_line>(x) )
} tmp << "\nThrow file line: " << *l;
std::string di2=exception_detail::boost_exception_diagnostic_information(&x,x); if( char const * s=exception_detail::get_diagnostic_information(x) )
if( !di2.empty() ) if( *s )
{ tmp << "\n" << s;
di+='\n'; return tmp.str();
di+=di2;
}
return di;
} }
} }

View File

@ -9,9 +9,6 @@
namespace namespace
boost boost
{ {
////////////////////////////////////////////////////////////////////////
namespace namespace
exception_detail exception_detail
{ {
@ -66,65 +63,77 @@ boost
add_ref() add_ref()
{ {
if( px_ ) if( px_ )
intrusive_ptr_add_ref(px_); px_->add_ref();
} }
void void
release() release()
{ {
if( px_ ) if( px_ )
intrusive_ptr_release(px_); px_->release();
} }
}; };
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
namespace template <class Tag,class T>
exception_detail class error_info;
{
typedef error_info<struct tag_throw_function,char const *> throw_function;
typedef error_info<struct tag_throw_file,char const *> throw_file;
typedef error_info<struct tag_throw_line,int> throw_line;
template <>
class class
counted_base error_info<tag_throw_function,char const *>
{ {
friend public:
void typedef char const * value_type;
intrusive_ptr_add_ref( counted_base const * c ) value_type v_;
{ explicit
c->add_ref(); error_info( value_type v ):
} v_(v)
friend
void
intrusive_ptr_release( counted_base const * c )
{
c->release();
}
virtual void add_ref() const=0;
virtual void release() const=0;
protected:
virtual
~counted_base() throw()
{ {
} }
}; };
}
//////////////////////////////////////////////////////////////////////// template <>
class
error_info<tag_throw_file,char const *>
{
public:
typedef char const * value_type;
value_type v_;
explicit
error_info( value_type v ):
v_(v)
{
}
};
template <>
class
error_info<tag_throw_line,int>
{
public:
typedef int value_type;
value_type v_;
explicit
error_info( value_type v ):
v_(v)
{
}
};
template <class E,class Tag,class T>
E const & operator<<( E const &, error_info<Tag,T> const & );
class exception; class exception;
template <class> template <class>
class shared_ptr; class shared_ptr;
template <class Tag,class T>
class error_info;
template <class E,class Tag,class T>
E const & operator<<( E const &, error_info<Tag,T> const & );
namespace namespace
exception_detail exception_detail
{ {
@ -132,62 +141,83 @@ boost
struct type_info_; struct type_info_;
struct struct
error_info_container: error_info_container
public exception_detail::counted_base
{ {
virtual char const * diagnostic_information() const = 0; virtual char const * diagnostic_information() const = 0;
virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0; virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0;
virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0; virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0;
virtual void add_ref() const = 0;
virtual void release() const = 0;
protected:
virtual
~error_info_container() throw()
{
}
}; };
template <class ErrorInfo> template <class>
shared_ptr<typename ErrorInfo::value_type const> get_info( exception const & ); struct get_info;
char const * get_diagnostic_information( exception const & );
} }
class class
exception exception
{ {
public:
virtual
char const *
diagnostic_information() const throw()
{
return _diagnostic_information();
}
protected: protected:
exception() exception():
throw_function_(0),
throw_file_(0),
throw_line_(-1)
{ {
} }
virtual ~exception() throw()=0; virtual ~exception() throw() = 0;
char const *
_diagnostic_information() const throw()
{
if( exception_detail::error_info_container * c=data_.get() )
try
{
if( char const * w = c->diagnostic_information() )
return w;
}
catch(...)
{
}
return "";
}
private: private:
template <class E>
friend
E const &
operator<<( E const & x, throw_function y )
{
x.throw_function_=y.v_;
return x;
}
template <class E>
friend
E const &
operator<<( E const & x, throw_file y )
{
x.throw_file_=y.v_;
return x;
}
template <class E>
friend
E const &
operator<<( E const & x, throw_line y )
{
x.throw_line_=y.v_;
return x;
}
friend char const * exception_detail::get_diagnostic_information( exception const & );
template <class E,class Tag,class T> template <class E,class Tag,class T>
friend E const & operator<<( E const &, error_info<Tag,T> const & ); friend E const & operator<<( E const &, error_info<Tag,T> const & );
template <class ErrorInfo> template <class>
friend shared_ptr<typename ErrorInfo::value_type const> exception_detail::get_info( exception const & ); friend struct exception_detail::get_info;
mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_; mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
mutable char const * throw_function_;
mutable char const * throw_file_;
mutable int throw_line_;
}; };
inline inline
@ -270,14 +300,12 @@ boost
virtual clone_base const * clone() const = 0; virtual clone_base const * clone() const = 0;
virtual void rethrow() const = 0; virtual void rethrow() const = 0;
virtual ~clone_base() throw() = 0;
};
inline virtual
clone_base::
~clone_base() throw() ~clone_base() throw()
{ {
} }
};
inline inline
void void
@ -322,7 +350,7 @@ boost
void void
rethrow() const rethrow() const
{ {
throw *this; throw*this;
} }
}; };
} }
@ -334,9 +362,6 @@ boost
{ {
return exception_detail::clone_impl<T>(x); return exception_detail::clone_impl<T>(x);
} }
////////////////////////////////////////////////////////////////////////
} }
#endif #endif

View File

@ -10,6 +10,7 @@
#include <boost/exception/detail/error_info_base.hpp> #include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp> #include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <memory.h>
namespace namespace
boost boost
@ -17,10 +18,93 @@ boost
namespace namespace
exception_detail exception_detail
{ {
struct
strwrap
{
char const * str;
strwrap( char const * s ):
str(init(s))
{
}
~strwrap()
{
delete[] str;
}
private:
strwrap( strwrap const & );
strwrap & operator=( strwrap const & );
static
char const *
init( char const * s )
{
size_t n=1+strlen(s);
char * str = new char[n];
(void) memcpy(str,s,n);
return str;
}
};
template <>
struct
get_info<throw_function>
{
static
shared_ptr<char const * const>
get( exception const & x )
{
if( x.throw_function_ )
{
shared_ptr<strwrap> s(new strwrap(x.throw_function_));
return shared_ptr<char const *>(s,&s->str);
}
else
return shared_ptr<char const * const>();
}
};
template <>
struct
get_info<throw_file>
{
static
shared_ptr<char const * const>
get( exception const & x )
{
if( x.throw_file_ )
{
shared_ptr<strwrap> s(new strwrap(x.throw_file_));
return shared_ptr<char const *>(s,&s->str);
}
else
return shared_ptr<char const * const>();
}
};
template <>
struct
get_info<throw_line>
{
static
shared_ptr<int const>
get( exception const & x )
{
if( x.throw_line_!=-1 )
return boost::shared_ptr<int>(new int(x.throw_line_));
else
return shared_ptr<int const>();
}
};
template <class ErrorInfo> template <class ErrorInfo>
inline struct
get_info
{
static
shared_ptr<typename ErrorInfo::value_type const> shared_ptr<typename ErrorInfo::value_type const>
get_info( exception const & x ) get( exception const & x )
{ {
if( exception_detail::error_info_container * c=x.data_.get() ) if( exception_detail::error_info_container * c=x.data_.get() )
if( shared_ptr<exception_detail::error_info_base const> eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) ) if( shared_ptr<exception_detail::error_info_base const> eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) )
@ -33,6 +117,7 @@ boost
} }
return shared_ptr<typename ErrorInfo::value_type const>(); return shared_ptr<typename ErrorInfo::value_type const>();
} }
};
} }
#ifdef BOOST_NO_RTTI #ifdef BOOST_NO_RTTI
@ -41,7 +126,7 @@ boost
shared_ptr<typename ErrorInfo::value_type const> shared_ptr<typename ErrorInfo::value_type const>
get_error_info( boost::exception const & x ) get_error_info( boost::exception const & x )
{ {
return exception_detail::get_info<ErrorInfo>(x); return exception_detail::get_info<ErrorInfo>::get(x);
} }
#else #else
template <class ErrorInfo,class E> template <class ErrorInfo,class E>
@ -50,7 +135,7 @@ boost
get_error_info( E const & some_exception ) get_error_info( E const & some_exception )
{ {
if( exception const * x = dynamic_cast<exception const *>(&some_exception) ) if( exception const * x = dynamic_cast<exception const *>(&some_exception) )
return exception_detail::get_info<ErrorInfo>(*x); return exception_detail::get_info<ErrorInfo>::get(*x);
else else
return shared_ptr<typename ErrorInfo::value_type const>(); return shared_ptr<typename ErrorInfo::value_type const>();
} }

View File

@ -7,25 +7,14 @@
#define UUID_8D22C4CA9CC811DCAA9133D256D89593 #define UUID_8D22C4CA9CC811DCAA9133D256D89593
#include <boost/exception/exception.hpp> #include <boost/exception/exception.hpp>
#include <boost/exception/error_info.hpp>
#include <boost/exception/to_string_stub.hpp> #include <boost/exception/to_string_stub.hpp>
#include <boost/exception/detail/error_info_base.hpp> #include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <map> #include <map>
#define BOOST_ERROR_INFO\
::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\
::boost::throw_file(__FILE__) <<\
::boost::throw_line((int)__LINE__)
namespace namespace
boost boost
{ {
typedef error_info<struct tag_throw_function,char const *> throw_function;
typedef error_info<struct tag_throw_file,char const *> throw_file;
typedef error_info<struct tag_throw_line,int> throw_line;
template <class Tag,class T> template <class Tag,class T>
class class
error_info: error_info:
@ -40,6 +29,10 @@ boost
{ {
} }
~error_info() throw()
{
}
value_type const & value_type const &
value() const value() const
{ {

View File

@ -8,161 +8,63 @@
#include <boost/exception/exception.hpp> #include <boost/exception/exception.hpp>
#include <boost/exception/detail/type_info.hpp> #include <boost/exception/detail/type_info.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <stdexcept> #include <stdexcept>
#include <new> #include <new>
namespace namespace
boost boost
{ {
namespace class exception_ptr;
exception_detail exception_ptr current_exception();
{ void rethrow_exception( exception_ptr const & );
class class
counted_clone: exception_ptr
public counted_base
{ {
public: typedef bool exception_ptr::*unspecified_bool_type;
friend exception_ptr current_exception();
friend void rethrow_exception( exception_ptr const & );
counted_clone(): shared_ptr<exception_detail::clone_base const> c_;
count_(0), bool bad_alloc_;
clone_(0)
{
}
void
set( clone_base const * c )
{
clone_ = c;
BOOST_ASSERT(clone_!=0);
}
void
rethrow() const
{
if( clone_ )
clone_->rethrow();
else
throw enable_current_exception(std::bad_alloc());
}
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_ )
delete clone_;
}
void
add_ref() const
{
++count_;
}
void
release() const
{
if( !--count_ )
delete this;
}
};
struct struct
bad_alloc_tag bad_alloc_tag
{ {
}; };
struct explicit
bad_exception_tag exception_ptr( bad_alloc_tag ):
bad_alloc_(true)
{ {
};
} }
class exception_ptr; explicit
void rethrow_exception( exception_ptr const & ); exception_ptr( shared_ptr<exception_detail::clone_base const> const & c ):
c_(c),
class bad_alloc_(false)
exception_ptr
{ {
private: BOOST_ASSERT(c);
friend void rethrow_exception( exception_ptr const & );
enum
{
bad_alloc_caught,
clone_failed,
ok
} what_happened_;
intrusive_ptr<exception_detail::counted_clone> 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_detail::counted_clone> exception_ptr::*unspecified_bool_type;
public: 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(): exception_ptr():
what_happened_(ok) bad_alloc_(false)
{ {
} }
explicit operator unspecified_bool_type() const
exception_ptr( intrusive_ptr<exception_detail::counted_clone> const & c ):
what_happened_(ok),
c_(c)
{ {
BOOST_ASSERT(c_.get()!=0); return (bad_alloc_ || c_) ? &exception_ptr::bad_alloc_ : 0;
} }
friend friend
bool bool
operator==( exception_ptr const & a, exception_ptr const & b ) operator==( exception_ptr const & a, exception_ptr const & b )
{ {
return return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_;
a.what_happened_==ok &&
b.what_happened_==ok &&
a.c_==b.c_;
} }
friend friend
@ -171,11 +73,6 @@ boost
{ {
return !(a==b); return !(a==b);
} }
operator unspecified_bool_type() const
{
return (what_happened_!=ok || c_) ? &exception_ptr::c_ : 0;
}
}; };
class class
@ -211,7 +108,7 @@ boost
void void
rethrow() const rethrow() const
{ {
throw *this; throw*this;
} }
}; };
@ -288,55 +185,42 @@ boost
template <class T> template <class T>
inline inline
exception_ptr shared_ptr<clone_base const>
current_exception_std_exception( T const & e1 ) current_exception_std_exception( T const & e1 )
{ {
intrusive_ptr<exception_detail::counted_clone> x(new exception_detail::counted_clone);
if( boost::exception const * e2 = get_boost_exception(&e1) ) if( boost::exception const * e2 = get_boost_exception(&e1) )
x->set(new current_exception_std_exception_wrapper<T>(e1,*e2)); return shared_ptr<clone_base const>(new current_exception_std_exception_wrapper<T>(e1,*e2));
else else
x->set(new current_exception_std_exception_wrapper<T>(e1)); return shared_ptr<clone_base const>(new current_exception_std_exception_wrapper<T>(e1));
return exception_ptr(x);
} }
inline inline
exception_ptr shared_ptr<clone_base const>
current_exception_unknown_exception() current_exception_unknown_exception()
{ {
intrusive_ptr<exception_detail::counted_clone> x(new exception_detail::counted_clone); return shared_ptr<clone_base const>(new unknown_exception());
x->set(new unknown_exception());
return exception_ptr(x);
} }
inline inline
exception_ptr shared_ptr<clone_base const>
current_exception_unknown_boost_exception( boost::exception const & e )
{
return shared_ptr<clone_base const>(new unknown_exception(e));
}
inline
shared_ptr<clone_base const>
current_exception_unknown_std_exception( std::exception const & e ) current_exception_unknown_std_exception( std::exception const & e )
{ {
if( boost::exception const * be = get_boost_exception(&e) ) if( boost::exception const * be = get_boost_exception(&e) )
{ return current_exception_unknown_boost_exception(*be);
intrusive_ptr<exception_detail::counted_clone> x(new exception_detail::counted_clone);
x->set(new unknown_exception(*be));
return exception_ptr(x);
}
else else
return current_exception_unknown_exception(); return current_exception_unknown_exception();
} }
inline inline
exception_ptr shared_ptr<clone_base const>
current_exception_unknown_boost_exception( boost::exception const & e ) current_exception_impl()
{
intrusive_ptr<exception_detail::counted_clone> x(new exception_detail::counted_clone);
x->set(new unknown_exception(e));
return exception_ptr(x);
}
}
inline
exception_ptr
current_exception()
{
try
{ {
try try
{ {
@ -345,9 +229,7 @@ boost
catch( catch(
exception_detail::clone_base & e ) exception_detail::clone_base & e )
{ {
intrusive_ptr<exception_detail::counted_clone> x(new exception_detail::counted_clone); return shared_ptr<exception_detail::clone_base const>(e.clone());
x->set(e.clone());
return exception_ptr(x);
} }
catch( catch(
std::invalid_argument & e ) std::invalid_argument & e )
@ -402,16 +284,38 @@ boost
return exception_detail::current_exception_unknown_exception(); return exception_detail::current_exception_unknown_exception();
} }
} }
}
inline
exception_ptr
current_exception()
{
try
{
return exception_ptr(exception_detail::current_exception_impl());
}
catch( catch(
std::bad_alloc & ) std::bad_alloc & )
{ {
return exception_ptr( exception_detail::bad_alloc_tag() );
} }
catch( catch(
... ) ... )
{ {
return exception_ptr( exception_detail::bad_exception_tag() ); try
{
return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception()));
} }
catch(
std::bad_alloc & )
{
}
catch(
... )
{
BOOST_ASSERT(0);
}
}
return exception_ptr(exception_ptr::bad_alloc_tag());
} }
template <class T> template <class T>
@ -423,7 +327,8 @@ boost
{ {
throw enable_current_exception(e); throw enable_current_exception(e);
} }
catch( ... ) catch(
... )
{ {
return current_exception(); return current_exception();
} }
@ -433,7 +338,11 @@ boost
void void
rethrow_exception( exception_ptr const & p ) rethrow_exception( exception_ptr const & p )
{ {
p.rethrow(); BOOST_ASSERT(p);
if( p.bad_alloc_ )
throw enable_current_exception(std::bad_alloc());
else
p.c_->rethrow();
} }
} }

View File

@ -38,6 +38,13 @@
#if !defined( BOOST_NO_EXCEPTIONS ) && !defined( BOOST_EXCEPTION_DISABLE ) #if !defined( BOOST_NO_EXCEPTIONS ) && !defined( BOOST_EXCEPTION_DISABLE )
# include <boost/exception/exception.hpp> # include <boost/exception/exception.hpp>
# include <boost/current_function.hpp>
# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(::boost::enable_error_info(x) <<\
::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\
::boost::throw_file(__FILE__) <<\
::boost::throw_line((int)__LINE__))
#else
# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)
#endif #endif
namespace boost namespace boost

View File

@ -23,7 +23,6 @@ run cloning_test.cpp ;
run copy_exception_test.cpp ; run copy_exception_test.cpp ;
run unknown_exception_test.cpp ; run unknown_exception_test.cpp ;
run exception_test.cpp ; run exception_test.cpp ;
run boost_error_info_test.cpp ;
run enable_error_info_test.cpp helper1.cpp ; run enable_error_info_test.cpp helper1.cpp ;
run throw_exception_test.cpp helper2.cpp ; run throw_exception_test.cpp helper2.cpp ;
run errno_test.cpp ; run errno_test.cpp ;

View File

@ -1,41 +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)
#include <boost/exception/get_error_info.hpp>
#include <boost/exception/info.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <stdexcept>
namespace
test
{
class my_exception: public boost::exception { };
typedef boost::error_info<struct tag_my_info,int> my_info;
void
test_boost_error_info()
{
try
{
throw my_exception() << BOOST_ERROR_INFO << my_info(1);
}
catch(
my_exception & x )
{
BOOST_TEST(1==*boost::get_error_info<my_info>(x));
BOOST_TEST(boost::get_error_info<boost::throw_function>(x));
BOOST_TEST(boost::get_error_info<boost::throw_file>(x));
BOOST_TEST(boost::get_error_info<boost::throw_line>(x));
}
}
}
int
main()
{
test::test_boost_error_info();
return boost::report_errors();
}

View File

@ -11,7 +11,8 @@ typedef boost::error_info<struct test_tag,int> tag_int;
struct struct
error1: error1:
public std::exception public std::exception,
public boost::exception
{ {
char const * char const *
what() const throw() what() const throw()
@ -22,18 +23,6 @@ error1:
struct struct
error2: error2:
public std::exception,
public boost::exception
{
char const *
what() const throw()
{
return "error2";
}
};
struct
error3:
public boost::exception public boost::exception
{ {
}; };
@ -44,56 +33,17 @@ main()
using namespace boost; using namespace boost;
try try
{ {
error1 x; error1 x; x << tag_int(42);
BOOST_TEST(x.what()==std::string("error1")); BOOST_TEST(x.what()==std::string("error1"));
throw x; throw x;
} }
catch( catch(
std::exception & x )
{
std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos);
BOOST_TEST(di.find("error1")!=std::string::npos);
}
catch(
... )
{
BOOST_TEST(false);
}
try
{
error2 x; x << tag_int(42);
BOOST_TEST(x.what()==std::string("error2"));
throw x;
}
catch(
std::exception & x )
{
std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos);
BOOST_TEST(di.find("error2")!=std::string::npos);
#ifndef BOOST_NO_RTTI
BOOST_TEST(di.find("test_tag")!=std::string::npos);
#endif
}
catch(
... )
{
BOOST_TEST(false);
}
try
{
error2 x; x << tag_int(42);
BOOST_TEST(x.what()==std::string("error2"));
throw x;
}
catch(
boost::exception & x ) boost::exception & x )
{ {
std::string di=boost::diagnostic_information(x); std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos);
#ifndef BOOST_NO_RTTI #ifndef BOOST_NO_RTTI
BOOST_TEST(di.find("error2")!=std::string::npos); BOOST_TEST(di.find("type:")!=std::string::npos);
BOOST_TEST(di.find("error1")!=std::string::npos);
#endif #endif
BOOST_TEST(di.find("test_tag")!=std::string::npos); BOOST_TEST(di.find("test_tag")!=std::string::npos);
} }
@ -104,7 +54,7 @@ main()
} }
try try
{ {
error3 x; error2 x;
x << tag_int(1); x << tag_int(1);
throw x; throw x;
} }

View File

@ -22,19 +22,17 @@ test_type
count_=42; count_=42;
} }
friend
void void
intrusive_ptr_add_ref( test_type const * c ) add_ref()
{ {
++c->count_; ++count_;
} }
friend
void void
intrusive_ptr_release( test_type const * c ) release()
{ {
if( !--c->count_ ) if( !--count_ )
delete c; delete this;
} }
private: private:

View File

@ -11,6 +11,66 @@
typedef boost::error_info<struct tag_test_int,int> test_data; typedef boost::error_info<struct tag_test_int,int> test_data;
struct
exception1:
std::exception
{
};
struct
exception2:
std::exception,
boost::exception
{
};
void
boost_throw_exception_test()
{
try
{
BOOST_THROW_EXCEPTION(exception1());
BOOST_TEST(false);
}
catch(
boost::exception & x )
{
boost::shared_ptr<char const * const> file=boost::get_error_info<boost::throw_function>(x);
boost::shared_ptr<char const * const> function=boost::get_error_info<boost::throw_file>(x);
boost::shared_ptr<int const> line=boost::get_error_info<boost::throw_line>(x);
BOOST_TEST( file && *file );
BOOST_TEST( function && *function );
BOOST_TEST( line && *line==32 );
}
catch(
... )
{
BOOST_TEST(false);
}
try
{
BOOST_THROW_EXCEPTION(exception2() << test_data(42));
BOOST_TEST(false);
}
catch(
boost::exception & x )
{
boost::shared_ptr<char const * const> file=boost::get_error_info<boost::throw_function>(x);
boost::shared_ptr<char const * const> function=boost::get_error_info<boost::throw_file>(x);
boost::shared_ptr<int const> line=boost::get_error_info<boost::throw_line>(x);
boost::shared_ptr<int const> data=boost::get_error_info<test_data>(x);
BOOST_TEST( file && *file );
BOOST_TEST( function && *function );
BOOST_TEST( line && *line==52 );
BOOST_TEST( data && *data==42 );
}
catch(
... )
{
BOOST_TEST(false);
}
}
void void
throw_fwd( void (*thrower)(int) ) throw_fwd( void (*thrower)(int) )
{ {
@ -80,6 +140,7 @@ tester()
int int
main() main()
{ {
boost_throw_exception_test();
tester<boost::exception_test::derives_boost_exception>(); tester<boost::exception_test::derives_boost_exception>();
tester<boost::exception_test::derives_boost_exception_virtually>(); tester<boost::exception_test::derives_boost_exception_virtually>();
tester<boost::exception_test::derives_std_exception>(); tester<boost::exception_test::derives_std_exception>();