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

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

View File

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

View File

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

View File

@ -6,9 +6,9 @@
#ifndef UUID_0552D49838DD11DD90146B8956D89593
#define UUID_0552D49838DD11DD90146B8956D89593
#include <boost/exception/exception.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/exception/get_error_info.hpp>
#include <exception>
#include <sstream>
#include <string>
namespace
@ -17,13 +17,27 @@ boost
namespace
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>
std::string
std_exception_diagnostic_information( std::exception const * x, T const & )
{
if( char const * s=x->what() )
if( *s )
return std::string("std::exception::what(): ")+s;
return std::string("\nstd::exception::what(): ")+s;
return std::string();
}
@ -35,58 +49,32 @@ boost
if( std::exception const * x=dynamic_cast<std::exception const *>(&e) )
return std_exception_diagnostic_information(x,e);
else
#endif
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
std::string
diagnostic_information( T const & x )
diagnostic_information( exception const & x )
{
std::string di=
#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID)
std::string("Static exception type: ")+BOOST_EXCEPTION_STATIC_TYPEID(T)
#else
std::string("Dynamic exception type: ")+BOOST_EXCEPTION_DYNAMIC_TYPEID(x)
std::ostringstream tmp;
tmp <<
"boost::exception diagnostic information:"
#if !defined(BOOST_NO_RTTI) && !defined(BOOST_NO_TYPEID)
"\nDynamic exception type: " << BOOST_EXCEPTION_DYNAMIC_TYPEID(x).name()
#endif
.name();
std::string di1=exception_detail::std_exception_diagnostic_information(&x,x);
if( !di1.empty() )
{
di+='\n';
di+=di1;
}
std::string di2=exception_detail::boost_exception_diagnostic_information(&x,x);
if( !di2.empty() )
{
di+='\n';
di+=di2;
}
return di;
;
if( boost::shared_ptr<char const * const> f=get_error_info<throw_function>(x) )
tmp << "\nThrow function: " << *f;
if( boost::shared_ptr<char const * const> f=get_error_info<throw_file>(x) )
tmp << "\nThrow file name: " << *f;
if( boost::shared_ptr<int const> l=get_error_info<throw_line>(x) )
tmp << "\nThrow file line: " << *l;
if( char const * s=exception_detail::get_diagnostic_information(x) )
if( *s )
tmp << "\n" << s;
return tmp.str();
}
}

View File

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

View File

@ -10,6 +10,7 @@
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp>
#include <memory.h>
namespace
boost
@ -17,22 +18,106 @@ boost
namespace
exception_detail
{
template <class ErrorInfo>
inline
shared_ptr<typename ErrorInfo::value_type const>
get_info( exception const & x )
struct
strwrap
{
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)) )
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_ )
{
#ifndef BOOST_NO_RTTI
BOOST_ASSERT( 0!=dynamic_cast<ErrorInfo const *>(eib.get()) );
#endif
ErrorInfo const * w = static_cast<ErrorInfo const *>(eib.get());
return shared_ptr<typename ErrorInfo::value_type const>(eib,&w->value());
shared_ptr<strwrap> s(new strwrap(x.throw_function_));
return shared_ptr<char const *>(s,&s->str);
}
return shared_ptr<typename ErrorInfo::value_type const>();
}
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>
struct
get_info
{
static
shared_ptr<typename ErrorInfo::value_type const>
get( exception const & x )
{
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)) )
{
#ifndef BOOST_NO_RTTI
BOOST_ASSERT( 0!=dynamic_cast<ErrorInfo const *>(eib.get()) );
#endif
ErrorInfo const * w = static_cast<ErrorInfo const *>(eib.get());
return shared_ptr<typename ErrorInfo::value_type const>(eib,&w->value());
}
return shared_ptr<typename ErrorInfo::value_type const>();
}
};
}
#ifdef BOOST_NO_RTTI
@ -41,7 +126,7 @@ boost
shared_ptr<typename ErrorInfo::value_type const>
get_error_info( boost::exception const & x )
{
return exception_detail::get_info<ErrorInfo>(x);
return exception_detail::get_info<ErrorInfo>::get(x);
}
#else
template <class ErrorInfo,class E>
@ -50,7 +135,7 @@ boost
get_error_info( E 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
return shared_ptr<typename ErrorInfo::value_type const>();
}

View File

@ -7,25 +7,14 @@
#define UUID_8D22C4CA9CC811DCAA9133D256D89593
#include <boost/exception/exception.hpp>
#include <boost/exception/error_info.hpp>
#include <boost/exception/to_string_stub.hpp>
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp>
#include <map>
#define BOOST_ERROR_INFO\
::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\
::boost::throw_file(__FILE__) <<\
::boost::throw_line((int)__LINE__)
namespace
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>
class
error_info:
@ -40,6 +29,10 @@ boost
{
}
~error_info() throw()
{
}
value_type const &
value() const
{
@ -159,7 +152,7 @@ boost
if( !(c=x.data_.get()) )
x.data_.adopt(c=new exception_detail::error_info_container_impl);
c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));
return x;
return x;
}
}

View File

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