mirror of
https://github.com/boostorg/exception.git
synced 2025-07-04 16:26:36 +02:00
support for exception_ptr and nesting in boost::diagnostic_information
documentation update [SVN r53038]
This commit is contained in:
@ -71,6 +71,7 @@ typedef boost::<span class="RenoLink">error_info</span><struct tag_errno,int&
|
|||||||
</a><a href="error_info_value_type.html">error_info::value_type<br/>
|
</a><a href="error_info_value_type.html">error_info::value_type<br/>
|
||||||
</a><a href="exception.html">exception<br/>
|
</a><a href="exception.html">exception<br/>
|
||||||
</a><a href="exception_operator_shl.html">exception/operator<<<br/>
|
</a><a href="exception_operator_shl.html">exception/operator<<<br/>
|
||||||
|
</a><a href="exception_ptr.html">exception_ptr<br/>
|
||||||
</a><a href="frequently_asked_questions.html">Frequently Asked Questions<br/>
|
</a><a href="frequently_asked_questions.html">Frequently Asked Questions<br/>
|
||||||
</a><a href="get_error_info.html">get_error_info<br/>
|
</a><a href="get_error_info.html">get_error_info<br/>
|
||||||
</a><a href="tutorial_enable_error_info.html">Integrating Boost Exception in Existing Exception Class Hierarchies<br/>
|
</a><a href="tutorial_enable_error_info.html">Integrating Boost Exception in Existing Exception Class Hierarchies<br/>
|
||||||
|
@ -55,6 +55,7 @@ boost
|
|||||||
</a><a href="exception_operator_shl.html">exception/operator<<<br/>
|
</a><a href="exception_operator_shl.html">exception/operator<<<br/>
|
||||||
</a><a href="exception_constructors.html">exception::exception<br/>
|
</a><a href="exception_constructors.html">exception::exception<br/>
|
||||||
</a><a href="exception_destructor.html">exception::~exception<br/>
|
</a><a href="exception_destructor.html">exception::~exception<br/>
|
||||||
|
</a><a href="exception_ptr.html">exception_ptr<br/>
|
||||||
</a><a href="frequently_asked_questions.html">Frequently Asked Questions<br/>
|
</a><a href="frequently_asked_questions.html">Frequently Asked Questions<br/>
|
||||||
</a><a href="get_error_info.html">get_error_info<br/>
|
</a><a href="get_error_info.html">get_error_info<br/>
|
||||||
</a><a href="tutorial_enable_error_info.html">Integrating Boost Exception in Existing Exception Class Hierarchies<br/>
|
</a><a href="tutorial_enable_error_info.html">Integrating Boost Exception in Existing Exception Class Hierarchies<br/>
|
||||||
|
@ -36,6 +36,8 @@ boost
|
|||||||
<li> It is illegal for multiple threads to modify the same <span class="RenoLink">exception_ptr</span> object concurrently.</li>
|
<li> It is illegal for multiple threads to modify the same <span class="RenoLink">exception_ptr</span> object concurrently.</li>
|
||||||
<li> While calling <span class="RenoLink"><a href="current_exception.html">current_exception</a></span> makes a copy of the current exception object, it is still possible for the two copies to share internal state. Therefore, in general it is not safe to call <span class="RenoLink"><a href="rethrow_exception.html">rethrow_exception</a></span> concurrently to throw the same exception object into multiple threads.</li>
|
<li> While calling <span class="RenoLink"><a href="current_exception.html">current_exception</a></span> makes a copy of the current exception object, it is still possible for the two copies to share internal state. Therefore, in general it is not safe to call <span class="RenoLink"><a href="rethrow_exception.html">rethrow_exception</a></span> concurrently to throw the same exception object into multiple threads.</li>
|
||||||
</ul></div>
|
</ul></div>
|
||||||
|
<h4>Nesting of exceptions</h4>
|
||||||
|
<p>An <span class="RenoLink">exception_ptr</span> can be added as <span class="RenoLink"><a href="error_info.html">error_info</a></span> to any boost::<span class="RenoLink"><a href="exception.html">exception</a></span>. This is a convenient way to nest exceptions. There is no limit on the depth of the nesting, however cyclic references result in undefined behavior.</p>
|
||||||
</div><div class="RenoAutoDIV"><div class="RenoHR"><hr/></div>
|
</div><div class="RenoAutoDIV"><div class="RenoHR"><hr/></div>
|
||||||
<h3>See Also:</h3>
|
<h3>See Also:</h3>
|
||||||
<div class="RenoPageList"><a href="boost-exception.html">Boost Exception<br/>
|
<div class="RenoPageList"><a href="boost-exception.html">Boost Exception<br/>
|
||||||
|
File diff suppressed because it is too large
Load Diff
26
include/boost/exception/detail/exception_ptr_base.hpp
Normal file
26
include/boost/exception/detail/exception_ptr_base.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//Copyright (c) 2006-2009 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_DC4208C6417811DEBF11E1EC55D89593
|
||||||
|
#define UUID_DC4208C6417811DEBF11E1EC55D89593
|
||||||
|
|
||||||
|
namespace
|
||||||
|
boost
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
exception_detail
|
||||||
|
{
|
||||||
|
class
|
||||||
|
exception_ptr_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void _rethrow() const=0;
|
||||||
|
virtual bool _empty() const=0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/exception/get_error_info.hpp>
|
#include <boost/exception/get_error_info.hpp>
|
||||||
|
#include <boost/exception/detail/exception_ptr_base.hpp>
|
||||||
#include <boost/utility/enable_if.hpp>
|
#include <boost/utility/enable_if.hpp>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -41,16 +42,6 @@ boost
|
|||||||
enum e { value = !enable_boost_exception_overload<T>::value && sizeof(check((T*)0))==sizeof(yes) };
|
enum e { value = !enable_boost_exception_overload<T>::value && sizeof(check((T*)0))==sizeof(yes) };
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef BOOST_NO_RTTI
|
|
||||||
template <class T>
|
|
||||||
inline
|
|
||||||
std::string
|
|
||||||
dynamic_exception_type( T const & x )
|
|
||||||
{
|
|
||||||
return std::string("Dynamic exception type: ") + BOOST_EXCEPTION_DYNAMIC_TYPEID(x).name();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
char const *
|
char const *
|
||||||
get_diagnostic_information( exception const & x )
|
get_diagnostic_information( exception const & x )
|
||||||
@ -72,45 +63,43 @@ boost
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
std::string
|
std::string
|
||||||
boost_diagnostic_information( exception const & x )
|
diagnostic_information_impl( boost::exception const * be, std::exception const * se )
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(be||se);
|
||||||
|
#ifndef BOOST_NO_RTTI
|
||||||
|
if( !se )
|
||||||
|
se = dynamic_cast<std::exception const *>(be);
|
||||||
|
if( !be )
|
||||||
|
be = dynamic_cast<boost::exception const *>(se);
|
||||||
|
#endif
|
||||||
std::ostringstream tmp;
|
std::ostringstream tmp;
|
||||||
if( char const * const * f=get_error_info<throw_file>(x) )
|
if( be )
|
||||||
|
{
|
||||||
|
if( char const * const * f=get_error_info<throw_file>(*be) )
|
||||||
{
|
{
|
||||||
tmp << *f;
|
tmp << *f;
|
||||||
if( int const * l=get_error_info<throw_line>(x) )
|
if( int const * l=get_error_info<throw_line>(*be) )
|
||||||
tmp << '(' << *l << "): ";
|
tmp << '(' << *l << "): ";
|
||||||
}
|
}
|
||||||
tmp << "Throw in function ";
|
tmp << "Throw in function ";
|
||||||
if( char const * const * fn=get_error_info<throw_function>(x) )
|
if( char const * const * fn=get_error_info<throw_function>(*be) )
|
||||||
tmp << *fn;
|
tmp << *fn;
|
||||||
else
|
else
|
||||||
tmp << "(unknown)";
|
tmp << "(unknown)";
|
||||||
tmp << std::endl;
|
tmp << '\n';
|
||||||
|
}
|
||||||
#ifndef BOOST_NO_RTTI
|
#ifndef BOOST_NO_RTTI
|
||||||
tmp << dynamic_exception_type(x) << std::endl;
|
tmp << std::string("Dynamic exception type: ") <<
|
||||||
if( std::exception const * e=dynamic_cast<std::exception const *>(&x) )
|
(be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).name() << '\n';
|
||||||
tmp << "std::exception::what: " << e->what() << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
if( char const * s=exception_detail::get_diagnostic_information(x) )
|
if( se )
|
||||||
|
tmp << "std::exception::what: " << se->what() << '\n';
|
||||||
|
if( be )
|
||||||
|
if( char const * s=exception_detail::get_diagnostic_information(*be) )
|
||||||
if( *s )
|
if( *s )
|
||||||
tmp << s;
|
tmp << s;
|
||||||
return tmp.str();
|
return tmp.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
|
||||||
std::string
|
|
||||||
std_diagnostic_information( std::exception const & x )
|
|
||||||
{
|
|
||||||
std::ostringstream tmp;
|
|
||||||
#ifndef BOOST_NO_RTTI
|
|
||||||
if( exception const * e=dynamic_cast<exception const *>(&x) )
|
|
||||||
return boost_diagnostic_information(*e);
|
|
||||||
tmp << dynamic_exception_type(x) << std::endl;
|
|
||||||
#endif
|
|
||||||
tmp << "std::exception::what: " << x.what() << std::endl;
|
|
||||||
return tmp.str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -118,7 +107,7 @@ boost
|
|||||||
typename enable_if<exception_detail::enable_boost_exception_overload<T>,std::string>::type
|
typename enable_if<exception_detail::enable_boost_exception_overload<T>,std::string>::type
|
||||||
diagnostic_information( T const & e )
|
diagnostic_information( T const & e )
|
||||||
{
|
{
|
||||||
return exception_detail::boost_diagnostic_information(e);
|
return exception_detail::diagnostic_information_impl(&e,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -126,7 +115,7 @@ boost
|
|||||||
typename enable_if<exception_detail::enable_std_exception_overload<T>,std::string>::type
|
typename enable_if<exception_detail::enable_std_exception_overload<T>,std::string>::type
|
||||||
diagnostic_information( T const & e )
|
diagnostic_information( T const & e )
|
||||||
{
|
{
|
||||||
return exception_detail::std_diagnostic_information(e);
|
return exception_detail::diagnostic_information_impl(0,&e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,13 +128,30 @@ boost
|
|||||||
std::string
|
std::string
|
||||||
current_exception_diagnostic_information()
|
current_exception_diagnostic_information()
|
||||||
{
|
{
|
||||||
if( boost::exception const * e=current_exception_cast<boost::exception const>() )
|
boost::exception const * be=current_exception_cast<boost::exception const>();
|
||||||
return diagnostic_information(*e);
|
std::exception const * se=current_exception_cast<std::exception const>();
|
||||||
else if( std::exception const * e=current_exception_cast<std::exception const>() )
|
if( be || se )
|
||||||
return diagnostic_information(*e);
|
return exception_detail::diagnostic_information_impl(be,se);
|
||||||
else
|
else
|
||||||
return "No diagnostic information available.";
|
return "No diagnostic information available.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::string
|
||||||
|
diagnostic_information( exception_detail::exception_ptr_base const & p )
|
||||||
|
{
|
||||||
|
if( !p._empty() )
|
||||||
|
try
|
||||||
|
{
|
||||||
|
p._rethrow();
|
||||||
|
}
|
||||||
|
catch(
|
||||||
|
... )
|
||||||
|
{
|
||||||
|
return current_exception_diagnostic_information();
|
||||||
|
}
|
||||||
|
return "<empty>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ boost
|
|||||||
for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
|
for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
|
||||||
{
|
{
|
||||||
shared_ptr<error_info_base const> const & x = i->second;
|
shared_ptr<error_info_base const> const & x = i->second;
|
||||||
tmp << '[' << x->tag_typeid_name() << "] = " << x->value_as_string() << std::endl;
|
tmp << '[' << x->tag_typeid_name() << "] = " << x->value_as_string() << '\n';
|
||||||
}
|
}
|
||||||
tmp.str().swap(diagnostic_info_str_);
|
tmp.str().swap(diagnostic_info_str_);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <boost/exception/exception.hpp>
|
#include <boost/exception/exception.hpp>
|
||||||
#include <boost/exception/info.hpp>
|
#include <boost/exception/info.hpp>
|
||||||
|
#include <boost/exception/diagnostic_information.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 <stdexcept>
|
#include <stdexcept>
|
||||||
@ -37,7 +38,8 @@ boost
|
|||||||
void rethrow_exception( exception_ptr const & );
|
void rethrow_exception( exception_ptr const & );
|
||||||
|
|
||||||
class
|
class
|
||||||
exception_ptr
|
exception_ptr:
|
||||||
|
public exception_detail::exception_ptr_base
|
||||||
{
|
{
|
||||||
typedef bool exception_ptr::*unspecified_bool_type;
|
typedef bool exception_ptr::*unspecified_bool_type;
|
||||||
friend exception_ptr current_exception();
|
friend exception_ptr current_exception();
|
||||||
@ -65,6 +67,22 @@ boost
|
|||||||
BOOST_ASSERT(c);
|
BOOST_ASSERT(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_rethrow() const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(*this);
|
||||||
|
if( bad_alloc_ )
|
||||||
|
throw enable_current_exception(std::bad_alloc());
|
||||||
|
else
|
||||||
|
c_->rethrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
_empty() const
|
||||||
|
{
|
||||||
|
return !bad_alloc_ && !c_;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
exception_ptr():
|
exception_ptr():
|
||||||
@ -74,7 +92,7 @@ boost
|
|||||||
|
|
||||||
operator unspecified_bool_type() const
|
operator unspecified_bool_type() const
|
||||||
{
|
{
|
||||||
return (bad_alloc_ || c_) ? &exception_ptr::bad_alloc_ : 0;
|
return _empty() ? 0 : &exception_ptr::bad_alloc_;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend
|
friend
|
||||||
@ -417,11 +435,26 @@ boost
|
|||||||
void
|
void
|
||||||
rethrow_exception( exception_ptr const & p )
|
rethrow_exception( exception_ptr const & p )
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(p);
|
p._rethrow();
|
||||||
if( p.bad_alloc_ )
|
}
|
||||||
throw enable_current_exception(std::bad_alloc());
|
|
||||||
else
|
inline
|
||||||
p.c_->rethrow();
|
std::string
|
||||||
|
to_string( exception_ptr const & p )
|
||||||
|
{
|
||||||
|
std::string s='\n'+diagnostic_information(p);
|
||||||
|
std::string padding(" ");
|
||||||
|
std::string r;
|
||||||
|
bool f=false;
|
||||||
|
for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i )
|
||||||
|
{
|
||||||
|
if( f )
|
||||||
|
r+=padding;
|
||||||
|
char c=*i;
|
||||||
|
r+=c;
|
||||||
|
f=(c=='\n');
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
struct my_tag {};
|
struct my_tag {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef boost::error_info<struct nested_exception_tag,boost::exception_ptr> nested_exception;
|
||||||
|
|
||||||
typedef boost::error_info<struct my_tag,int> my_info;
|
typedef boost::error_info<struct my_tag,int> my_info;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -69,6 +71,17 @@ derives_std_boost_exception:
|
|||||||
std::exception,
|
std::exception,
|
||||||
boost::exception
|
boost::exception
|
||||||
{
|
{
|
||||||
|
char const * const wh_;
|
||||||
|
|
||||||
|
derives_std_boost_exception( char const * wh="derives_std_boost_exception" ):
|
||||||
|
wh_(wh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * what() const throw()
|
||||||
|
{
|
||||||
|
return wh_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@ -530,5 +543,30 @@ main()
|
|||||||
test_throw_on_copy<std::bad_alloc,std::bad_alloc>();
|
test_throw_on_copy<std::bad_alloc,std::bad_alloc>();
|
||||||
test_throw_on_copy<int,std::bad_exception>();
|
test_throw_on_copy<int,std::bad_exception>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw boost::enable_current_exception(derives_std_boost_exception("what1"));
|
||||||
|
}
|
||||||
|
catch(
|
||||||
|
... )
|
||||||
|
{
|
||||||
|
boost::exception_ptr p=boost::current_exception();
|
||||||
|
{
|
||||||
|
std::string s=diagnostic_information(p);
|
||||||
|
BOOST_TEST(s.find("what1")!=s.npos);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw boost::enable_current_exception(derives_std_boost_exception("what2") << nested_exception(p) );
|
||||||
|
}
|
||||||
|
catch(
|
||||||
|
... )
|
||||||
|
{
|
||||||
|
std::string s=boost::current_exception_diagnostic_information();
|
||||||
|
BOOST_TEST(s.find("what1")!=s.npos);
|
||||||
|
BOOST_TEST(s.find("what2")!=s.npos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_TEST(!diagnostic_information(boost::exception_ptr()).empty());
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user