mirror of
https://github.com/boostorg/exception.git
synced 2025-07-23 09:07:15 +02:00
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:
@ -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()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include <boost/exception/detail/type_info.hpp>
|
||||
#include <iomanip>
|
||||
#include <typeinfo>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user