diff --git a/doc/source/boost-exception.reno b/doc/source/boost-exception.reno
index 671893b..9d42405 100644
--- a/doc/source/boost-exception.reno
+++ b/doc/source/boost-exception.reno
@@ -54,14 +54,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
156B870761DB092CE4269C1173B479A344A1041BA2B883765AF19A72B371D776
3239976720
117
- 4756
+ 6700
@@ -152,14 +152,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
- ED09F845070FF7D381BE5EFB6B55313FD09FBA16B64B69992410380EFA45519C
- 2051939590
- 78
- 433
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
+ AB48477C625A1E68BF74B055D380697B5761C4DBA41F8B2148F6A0F8A2BAC38E
+ 3683655261
+ 81
+ 1480
@@ -250,10 +250,10 @@
1
- 06FF83AB627CF01DE016240E3664241F90A142A3963F0EAFAE55E4A11742D7FC
- 3393983433
- 3433
- 227
+ 59EC111578A82535A1DC3EDB486F029664F751D86C2C90D0D3FE0BAFAA87387E
+ 3274250395
+ 3418
+ 323
@@ -295,9 +295,9 @@
1
- 208AD3E1D28FC8033210811C4E44D738A41F0B0B7F747467413A685125A50544
- 2712565394
- 5087
+ F052D2548BCDFFFA0DA6CB0AC3731B15EBE7E34F357A4485F0FCD205457859CA
+ 175131392
+ 7021
323
@@ -749,14 +749,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
F87D7E0321BDDAE23D5A6667CB12116411468AEC54E3B35FB9C8CA94BFECA41E
1149388739
296
- 4458
+ 6402
@@ -1161,14 +1161,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
- 9DEEF8ED70BF74F501A96BA5DE5BFD42FAD16DE333ABE189E512C332586FC465
- 2250569940
- 1893
- 2563
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
+ 5B9A60CD7925F05B8F4A0A8F690EC320226187C26D9D6DD9F3A7793C74A9F4FC
+ 3344368450
+ 1912
+ 4488
@@ -1545,14 +1545,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
A098B6FA5BC8E72E0E69C0323195FCC142AE807564C6892FCBD88588F2FBE049
2579522516
405
- 26
+ 1563
@@ -1594,14 +1594,14 @@
2
- BC2FB1723D280E870C34C192CB356C520C5C1C23EA5C209797F5DE3F15758F24
- 997637066
- 3154
- 506
+ 3A4D0506DEDA25E46C6F3B3936898F829C428AF153A7B1B5391B02ABA4C0AD0D
+ 1800726291
+ 3277
+ 464
DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9
1137981799
192
- 2956
+ 3079
@@ -7787,6 +7787,34 @@
-39
+
+
+
+
+ 2
+ 3A4D0506DEDA25E46C6F3B3936898F829C428AF153A7B1B5391B02ABA4C0AD0D
+ 1800726291
+ 3277
+ 464
+ DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9
+ 1137981799
+ 192
+ 3079
+
+
+
+
+
+ 0
+ ../../../../boost/exception/enable_current_exception.hpp
+ 0
+ 0
+
+
+
+ -38
+
+
@@ -7840,42 +7868,14 @@
2
- BC2FB1723D280E870C34C192CB356C520C5C1C23EA5C209797F5DE3F15758F24
- 997637066
- 3154
- 506
- DF9EA87B0140AACF4422F1B76F6A6A409C15F32858BBBA85A35981A824C56BA9
- 1137981799
- 192
- 2956
-
-
-
-
-
- 0
- ../../../../boost/exception/enable_current_exception.hpp
- 0
- 0
-
-
-
- -38
-
-
-
-
-
-
- 2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
F87D7E0321BDDAE23D5A6667CB12116411468AEC54E3B35FB9C8CA94BFECA41E
1149388739
296
- 4458
+ 6402
@@ -7896,14 +7896,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
A098B6FA5BC8E72E0E69C0323195FCC142AE807564C6892FCBD88588F2FBE049
2579522516
405
- 26
+ 1563
@@ -7924,42 +7924,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
- 9DEEF8ED70BF74F501A96BA5DE5BFD42FAD16DE333ABE189E512C332586FC465
- 2250569940
- 1893
- 2563
-
-
-
-
-
- 0
- ../../../../boost/exception_ptr.hpp
- 0
- 0
-
-
-
- -29
-
-
-
-
-
-
- 2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
156B870761DB092CE4269C1173B479A344A1041BA2B883765AF19A72B371D776
3239976720
117
- 4756
+ 6700
@@ -7980,14 +7952,14 @@
2
- 0FEF784CA0A4FF86352946012E280A01EA22BA7DF8A19B243DC76A5125D4042F
- 3547540308
- 4879
- 531
- ED09F845070FF7D381BE5EFB6B55313FD09FBA16B64B69992410380EFA45519C
- 2051939590
- 78
- 433
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
+ AB48477C625A1E68BF74B055D380697B5761C4DBA41F8B2148F6A0F8A2BAC38E
+ 3683655261
+ 81
+ 1480
@@ -8003,6 +7975,34 @@
-7
+
+
+
+
+ 2
+ 548365B35C2AA24908DAA42A1F359940FCD1DE69D642E074E821AC86DCE54029
+ 3649242015
+ 6823
+ 521
+ 5B9A60CD7925F05B8F4A0A8F690EC320226187C26D9D6DD9F3A7793C74A9F4FC
+ 3344368450
+ 1912
+ 4488
+
+
+
+
+
+ 0
+ ../../../../boost/exception_ptr.hpp
+ 0
+ 0
+
+
+
+ -29
+
+
@@ -8075,30 +8075,6 @@
-21
-
-
-
-
- 1
- 208AD3E1D28FC8033210811C4E44D738A41F0B0B7F747467413A685125A50544
- 2712565394
- 5087
- 323
-
-
-
-
-
- 0
- ../../../../boost/exception_ptr.hpp
- 0
- 0
-
-
-
- -10
-
-
@@ -8431,6 +8407,30 @@
-40
+
+
+
+
+ 1
+ 59EC111578A82535A1DC3EDB486F029664F751D86C2C90D0D3FE0BAFAA87387E
+ 3274250395
+ 3418
+ 323
+
+
+
+
+
+ 0
+ ../../../../boost/exception/enable_current_exception.hpp
+ 0
+ 0
+
+
+
+ -9
+
+
@@ -8531,6 +8531,30 @@
-35
+
+
+
+
+ 1
+ F052D2548BCDFFFA0DA6CB0AC3731B15EBE7E34F357A4485F0FCD205457859CA
+ 175131392
+ 7021
+ 323
+
+
+
+
+
+ 0
+ ../../../../boost/exception_ptr.hpp
+ 0
+ 0
+
+
+
+ -10
+
+
@@ -8711,30 +8735,6 @@
-19
-
-
-
-
- 1
- 06FF83AB627CF01DE016240E3664241F90A142A3963F0EAFAE55E4A11742D7FC
- 3393983433
- 3433
- 227
-
-
-
-
-
- 0
- ../../../../boost/exception/enable_current_exception.hpp
- 0
- 0
-
-
-
- -9
-
-
diff --git a/include/boost/exception/detail/cloning_base.hpp b/include/boost/exception/detail/cloning_base.hpp
index 5e5ff66..ad423fe 100644
--- a/include/boost/exception/detail/cloning_base.hpp
+++ b/include/boost/exception/detail/cloning_base.hpp
@@ -16,12 +16,19 @@ boost
{
class clone_base;
+ struct
+ new_clone
+ {
+ clone_base const * c_;
+ void (*d_)(clone_base const *);
+ };
+
class
cloning_base
{
public:
- virtual clone_base const * clone() const = 0;
+ virtual new_clone clone() const = 0;
protected:
diff --git a/include/boost/exception/enable_current_exception.hpp b/include/boost/exception/enable_current_exception.hpp
index d350b4d..f39234e 100644
--- a/include/boost/exception/enable_current_exception.hpp
+++ b/include/boost/exception/enable_current_exception.hpp
@@ -8,7 +8,6 @@
#include
#include
-#include
#include
#include
@@ -31,39 +30,8 @@ boost
{
}
- 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
- clone_base * make_clone( T const & );
+ new_clone make_clone( T const & );
template
class
@@ -80,15 +48,46 @@ boost
copy_boost_exception(this,&x);
}
+ ~clone_impl() throw()
+ {
+ }
+
private:
- clone_base const *
+ new_clone
clone() const
{
return make_clone(*this);
}
};
+ class
+ clone_base
+ {
+ public:
+
+ virtual void rethrow() const=0;
+ virtual ~clone_base() throw()=0;
+ };
+
+ inline
+ clone_base::
+ ~clone_base() throw()
+ {
+ }
+
+ struct
+ bad_alloc_impl:
+ public clone_base,
+ public std::bad_alloc
+ {
+ void
+ rethrow() const
+ {
+ throw *this;
+ }
+ };
+
template
class
exception_clone:
@@ -99,27 +98,15 @@ boost
explicit
exception_clone( T const & x ):
- T(x),
- count_(0)
+ T(x)
{
copy_boost_exception(this,&x);
}
private:
- mutable detail::atomic_count count_;
-
- void
- add_ref() const
+ ~exception_clone() throw()
{
- ++count_;
- }
-
- void
- release() const
- {
- if( !--count_ )
- delete this;
}
void
@@ -129,27 +116,44 @@ boost
}
};
+ inline
+ void
+ delete_clone( clone_base const * c )
+ {
+ BOOST_ASSERT(c!=0);
+ delete c;
+ }
+
+ inline
+ void
+ delete_clone_noop( clone_base const * )
+ {
+ }
+
template
inline
- clone_base *
+ new_clone
make_clone( T const & x )
{
+ new_clone tmp = {0,0};
try
{
- return new exception_clone(x);
+ tmp.c_=new exception_clone(x);
+ tmp.d_=&delete_clone;
}
catch(
std::bad_alloc & )
{
static bad_alloc_impl bad_alloc;
- return &bad_alloc;
+ tmp.c_=&bad_alloc;
+ tmp.d_=&delete_clone_noop;
}
catch(
... )
{
BOOST_ASSERT(0);
- return 0;
}
+ return tmp;
}
}
diff --git a/include/boost/exception_ptr.hpp b/include/boost/exception_ptr.hpp
index cb1d73e..94330fd 100644
--- a/include/boost/exception_ptr.hpp
+++ b/include/boost/exception_ptr.hpp
@@ -8,13 +8,76 @@
#include
#include
-#include
+#include
#include
#include
namespace
boost
{
+ namespace
+ exception_detail
+ {
+ class
+ counted_clone:
+ public counted_base
+ {
+ public:
+
+ counted_clone():
+ count_(0),
+ clone_(0)
+ {
+ }
+
+ void
+ set( new_clone const & nc )
+ {
+ clone_ = nc.c_;
+ clone_deleter_ = nc.d_;
+ BOOST_ASSERT(clone_!=0);
+ BOOST_ASSERT(clone_deleter_!=0);
+ }
+
+ void
+ rethrow() const
+ {
+ BOOST_ASSERT(clone_!=0);
+ clone_->rethrow();
+ }
+
+ 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_ )
+ clone_deleter_(clone_);
+ }
+
+ void
+ add_ref() const
+ {
+ ++count_;
+ }
+
+ void
+ release() const
+ {
+ if( !--count_ )
+ delete this;
+ }
+ };
+ }
+
+ typedef intrusive_ptr exception_ptr;
+
class
unknown_exception:
public exception,
@@ -37,8 +100,6 @@ boost
}
};
- typedef intrusive_ptr exception_ptr;
-
namespace
exception_detail
{
@@ -72,17 +133,21 @@ boost
exception_ptr
current_exception_std_exception( T const & e1 )
{
+ intrusive_ptr x(new exception_detail::counted_clone);
if( boost::exception const * e2 = get_boost_exception(&e1) )
- return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2)));
+ x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2)));
else
- return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1)));
+ x->set(exception_detail::make_clone(current_exception_std_exception_wrapper(e1)));
+ return x;
}
inline
exception_ptr
current_exception_unknown_exception()
{
- return exception_ptr(exception_detail::make_clone(unknown_exception()));
+ intrusive_ptr x(new exception_detail::counted_clone);
+ x->set(exception_detail::make_clone(unknown_exception()));
+ return x;
}
inline
@@ -90,7 +155,11 @@ boost
current_exception_unknown_std_exception( std::exception const & e )
{
if( boost::exception const * be = get_boost_exception(&e) )
- return exception_ptr(exception_detail::make_clone(unknown_exception(*be)));
+ {
+ intrusive_ptr x(new exception_detail::counted_clone);
+ x->set(exception_detail::make_clone(unknown_exception(*be)));
+ return x;
+ }
else
return current_exception_unknown_exception();
}
@@ -99,7 +168,9 @@ boost
exception_ptr
current_exception_unknown_boost_exception( boost::exception const & e )
{
- return exception_ptr(exception_detail::make_clone(unknown_exception(e)));
+ intrusive_ptr x(new exception_detail::counted_clone);
+ x->set(exception_detail::make_clone(unknown_exception(e)));
+ return x;
}
}
@@ -114,9 +185,9 @@ boost
catch(
exception_detail::cloning_base & e )
{
- exception_detail::clone_base const * c = e.clone();
- BOOST_ASSERT(c!=0);
- return exception_ptr(c);
+ intrusive_ptr x(new exception_detail::counted_clone);
+ x->set(e.clone());
+ return x;
}
catch(
std::invalid_argument & e )
diff --git a/test/cloning_test.cpp b/test/cloning_test.cpp
index 5f2319a..62e1de1 100644
--- a/test/cloning_test.cpp
+++ b/test/cloning_test.cpp
@@ -4,20 +4,63 @@
//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include
+#include
+#include
#include
+#include
+
+typedef boost::error_info my_info;
struct
-test_exception:
+derives_nothing
+ {
+ int & count;
+
+ explicit
+ derives_nothing( int & count ):
+ count(count)
+ {
+ ++count;
+ }
+
+ derives_nothing( derives_nothing const & x ):
+ count(x.count)
+ {
+ ++count;
+ }
+
+ ~derives_nothing()
+ {
+ --count;
+ }
+ };
+
+struct
+derives_std_exception:
std::exception
{
};
-int
-main()
+struct
+derives_std_boost_exception:
+ std::exception,
+ boost::exception
+ {
+ };
+
+struct
+derives_boost_exception:
+ boost::exception
+ {
+ };
+
+template
+void
+test_std_exception()
{
try
{
- throw boost::enable_current_exception(test_exception());
+ throw T();
}
catch(
... )
@@ -29,7 +72,7 @@ main()
BOOST_TEST(false);
}
catch(
- test_exception & )
+ T & )
{
}
catch(
@@ -38,5 +81,176 @@ main()
BOOST_TEST(false);
}
}
+ }
+
+template
+void
+test_std_exception_what()
+ {
+ try
+ {
+ throw T("what");
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ T & x )
+ {
+ BOOST_TEST(std::string("what")==x.what());
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+ }
+
+int
+main()
+ {
+ int count=0;
+ try
+ {
+ throw boost::enable_current_exception(derives_nothing(count));
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ derives_nothing & )
+ {
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+ BOOST_TEST(count==0);
+
+ try
+ {
+ throw boost::enable_current_exception(derives_std_exception());
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ derives_std_exception & )
+ {
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+
+ try
+ {
+ throw derives_std_exception();
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ boost::unknown_exception & )
+ {
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+
+ test_std_exception_what();
+ test_std_exception_what();
+ test_std_exception_what();
+ test_std_exception();
+ test_std_exception();
+ test_std_exception();
+ test_std_exception();
+
+ try
+ {
+ throw derives_std_boost_exception() << my_info(42);
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ boost::unknown_exception & x )
+ {
+ BOOST_TEST(boost::get_error_info(x));
+ if( boost::shared_ptr p=boost::get_error_info(x) )
+ BOOST_TEST(*p==42);
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+
+ try
+ {
+ throw derives_boost_exception() << my_info(42);
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr p = boost::current_exception();
+ try
+ {
+ rethrow_exception(p);
+ BOOST_TEST(false);
+ }
+ catch(
+ boost::unknown_exception & x )
+ {
+ BOOST_TEST(boost::get_error_info(x));
+ if( boost::shared_ptr p=boost::get_error_info(x) )
+ BOOST_TEST(*p==42);
+ }
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+
return boost::report_errors();
}