diff --git a/doc/copy_exception.html b/doc/copy_exception.html index 1f85935..906ceed 100644 --- a/doc/copy_exception.html +++ b/doc/copy_exception.html @@ -39,7 +39,7 @@ catch(...) return current_exception(); }

-See also: Boost Exception | boost/exception_ptr.hpp +See also: Boost Exception | boost/exception_ptr.hpp | current_exception
diff --git a/doc/current_exception.html b/doc/current_exception.html index 1533e4a..d8b369b 100644 --- a/doc/current_exception.html +++ b/doc/current_exception.html @@ -29,6 +29,7 @@ boost }

Requirements:

The current_exception function must not be called outside of a catch block.

+

In addition, to safely copy an exception from one thread to another, if the exception object is copied by current_exception or copy_exception, the two copies must not have shared state. Exceptions that have value-type semantics (as well as the boost::exception type itself) satisfy this requirement.

Returns:


-See also: Boost Exception | boost/exception_ptr.hpp | copy_exception | enable_current_exception | exception_ptr | Frequently Asked Questions | original_exception_type | unknown_exception +See also: Boost Exception | boost/exception_ptr.hpp | copy_exception | enable_current_exception | Frequently Asked Questions | original_exception_type | unknown_exception
diff --git a/doc/exception_ptr.html b/doc/exception_ptr.html index f5f362b..5e18b2f 100644 --- a/doc/exception_ptr.html +++ b/doc/exception_ptr.html @@ -31,11 +31,12 @@ boost

The referenced object remains valid at least as long as there is an exception_ptr object that refers to it.

Two instances of exception_ptr are equivalent and compare equal if and only if they refer to the same exception.

The default constructor of exception_ptr produces the null value of the type. The null value is equivalent only to itself.

-

Thread safety

-

diff --git a/doc/rethrow_exception.html b/doc/rethrow_exception.html index fc6577c..e335e35 100644 --- a/doc/rethrow_exception.html +++ b/doc/rethrow_exception.html @@ -32,7 +32,7 @@ boost

Throws:

The exception to which ep refers.


-See also: Boost Exception | boost/exception_ptr.hpp | diagnostic_information | exception_ptr +See also: Boost Exception | boost/exception_ptr.hpp | diagnostic_information
diff --git a/include/boost/exception/detail/error_info_impl.hpp b/include/boost/exception/detail/error_info_impl.hpp index 32113b1..883d313 100644 --- a/include/boost/exception/detail/error_info_impl.hpp +++ b/include/boost/exception/detail/error_info_impl.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 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) @@ -25,7 +25,7 @@ boost { public: - virtual char const * tag_typeid_name() const = 0; + virtual std::string tag_typeid_name() const = 0; virtual std::string value_as_string() const = 0; protected: @@ -62,7 +62,7 @@ boost private: - char const * tag_typeid_name() const; + std::string tag_typeid_name() const; std::string value_as_string() const; value_type value_; diff --git a/include/boost/exception/detail/exception_ptr.hpp b/include/boost/exception/detail/exception_ptr.hpp index 78db17c..59686e9 100644 --- a/include/boost/exception/detail/exception_ptr.hpp +++ b/include/boost/exception/detail/exception_ptr.hpp @@ -28,6 +28,26 @@ namespace boost { + typedef shared_ptr exception_ptr; + + exception_ptr current_exception(); + + template + inline + exception_ptr + copy_exception( T const & e ) + { + try + { + throw enable_current_exception(e); + } + catch( + ... ) + { + return current_exception(); + } + } + #ifndef BOOST_NO_RTTI typedef error_info original_exception_type; @@ -39,91 +59,45 @@ boost } #endif - class exception_ptr; - exception_ptr current_exception(); - void rethrow_exception( exception_ptr const & ); - - class - exception_ptr + namespace + exception_detail { - typedef bool exception_ptr::*unspecified_bool_type; - friend exception_ptr current_exception(); - friend void rethrow_exception( exception_ptr const & ); - - shared_ptr c_; - bool bad_alloc_; - struct - bad_alloc_tag + bad_alloc_: + boost::exception, + std::bad_alloc + { + }; + + template + exception_ptr + get_bad_alloc() { + static exception_ptr e = boost::copy_exception( + bad_alloc_() << + throw_function("boost::current_exception()") << + throw_file(__FILE__) << + throw_line(__LINE__) ); + return e; + } + + template + struct + exception_ptr_bad_alloc + { + static exception_ptr const e; }; - explicit - exception_ptr( bad_alloc_tag ): - bad_alloc_(true) - { - } - - explicit - exception_ptr( shared_ptr const & c ): - c_(c), - bad_alloc_(false) - { - 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: - - exception_ptr(): - bad_alloc_(false) - { - } - - ~exception_ptr() throw() - { - } - - operator unspecified_bool_type() const - { - return empty() ? 0 : &exception_ptr::bad_alloc_; - } - - friend - bool - operator==( exception_ptr const & a, exception_ptr const & b ) - { - return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_; - } - - friend - bool - operator!=( exception_ptr const & a, exception_ptr const & b ) - { - return !(a==b); - } - }; + template + exception_ptr const + exception_ptr_bad_alloc:: + e = get_bad_alloc(); + } class unknown_exception: - public exception, - public std::exception, - public exception_detail::clone_base + public boost::exception, + public std::exception { public: @@ -150,18 +124,6 @@ boost private: - exception_detail::clone_base const * - clone() const - { - return new unknown_exception(*this); - } - - void - rethrow() const - { - throw*this; - } - template void add_original_type( E const & e ) @@ -179,8 +141,7 @@ boost class current_exception_std_exception_wrapper: public T, - public boost::exception, - public clone_base + public boost::exception { public: @@ -204,18 +165,6 @@ boost private: - clone_base const * - clone() const - { - return new current_exception_std_exception_wrapper(*this); - } - - void - rethrow() const - { - throw *this; - } - template void add_original_type( E const & e ) @@ -228,7 +177,7 @@ boost #ifdef BOOST_NO_RTTI template - exception const * + boost::exception const * get_boost_exception( T const * ) { try @@ -236,7 +185,7 @@ boost throw; } catch( - exception & x ) + boost::exception & x ) { return &x; } @@ -247,50 +196,50 @@ boost } #else template - exception const * + boost::exception const * get_boost_exception( T const * x ) { - return dynamic_cast(x); + return dynamic_cast(x); } #endif template inline - shared_ptr + exception_ptr current_exception_std_exception( T const & e1 ) { if( boost::exception const * e2 = get_boost_exception(&e1) ) - return shared_ptr const>(new current_exception_std_exception_wrapper(e1,*e2)); + return boost::copy_exception(current_exception_std_exception_wrapper(e1,*e2)); else - return shared_ptr const>(new current_exception_std_exception_wrapper(e1)); + return boost::copy_exception(current_exception_std_exception_wrapper(e1)); } inline - shared_ptr + exception_ptr current_exception_unknown_exception() { - return shared_ptr(new unknown_exception()); + return boost::copy_exception(unknown_exception()); } inline - shared_ptr + exception_ptr current_exception_unknown_boost_exception( boost::exception const & e ) { - return shared_ptr(new unknown_exception(e)); + return boost::copy_exception(unknown_exception(e)); } inline - shared_ptr + exception_ptr current_exception_unknown_std_exception( std::exception const & e ) { if( boost::exception const * be = get_boost_exception(&e) ) return current_exception_unknown_boost_exception(*be); else - return shared_ptr(new unknown_exception(e)); + return boost::copy_exception(unknown_exception(e)); } inline - shared_ptr + exception_ptr current_exception_impl() { try @@ -300,7 +249,7 @@ boost catch( exception_detail::clone_base & e ) { - return shared_ptr(e.clone()); + return exception_ptr(e.clone()); } catch( std::domain_error & e ) @@ -396,24 +345,28 @@ boost exception_ptr current_exception() { + exception_ptr ret; + BOOST_ASSERT(!ret); try { - return exception_ptr(exception_detail::current_exception_impl()); + ret=exception_detail::current_exception_impl(); } catch( std::bad_alloc & ) { + ret=exception_detail::exception_ptr_bad_alloc<42>::e; } catch( ... ) { try { - return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception())); + ret=exception_detail::current_exception_std_exception(std::bad_exception()); } catch( std::bad_alloc & ) { + ret=exception_detail::exception_ptr_bad_alloc<42>::e; } catch( ... ) @@ -421,30 +374,16 @@ boost BOOST_ASSERT(0); } } - return exception_ptr(exception_ptr::bad_alloc_tag()); - } - - template - inline - exception_ptr - copy_exception( T const & e ) - { - try - { - throw enable_current_exception(e); - } - catch( - ... ) - { - return current_exception(); - } + BOOST_ASSERT(ret); + return ret; } inline void rethrow_exception( exception_ptr const & p ) { - p.rethrow(); + BOOST_ASSERT(p); + p->rethrow(); } inline diff --git a/include/boost/exception/detail/is_output_streamable.hpp b/include/boost/exception/detail/is_output_streamable.hpp index 5eb1695..743313c 100644 --- a/include/boost/exception/detail/is_output_streamable.hpp +++ b/include/boost/exception/detail/is_output_streamable.hpp @@ -20,8 +20,21 @@ boost namespace to_string_detail { - template - char operator<<( std::basic_ostream &, T const & ); + struct + partial_ordering_helper1 + { + template + partial_ordering_helper1( std::basic_ostream & ); + }; + + struct + partial_ordering_helper2 + { + template + partial_ordering_helper2( T const & ); + }; + + char operator<<( partial_ordering_helper1, partial_ordering_helper2 ); template struct diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp index 60709a1..9ab1c57 100644 --- a/include/boost/exception/detail/type_info.hpp +++ b/include/boost/exception/detail/type_info.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 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) @@ -15,31 +15,35 @@ #include #include #include +#ifndef BOOST_NO_TYPEID +#include +#endif +#include namespace boost { template inline - char const * + std::string tag_type_name() { #ifdef BOOST_NO_TYPEID return BOOST_CURRENT_FUNCTION; #else - return typeid(T*).name(); + return units::detail::demangle(typeid(T*).name()); #endif } template inline - char const * + std::string type_name() { #ifdef BOOST_NO_TYPEID return BOOST_CURRENT_FUNCTION; #else - return typeid(T).name(); + return units::detail::demangle(typeid(T).name()); #endif } diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp index 632a5a3..1d6bc2c 100644 --- a/include/boost/exception/diagnostic_information.hpp +++ b/include/boost/exception/diagnostic_information.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 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) @@ -15,7 +15,9 @@ #include #include #include -#include +#ifndef BOOST_NO_RTTI +#include +#endif #include #include #include @@ -135,7 +137,7 @@ boost } #ifndef BOOST_NO_RTTI tmp << std::string("Dynamic exception type: ") << - (be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).type_.name() << '\n'; + units::detail::demangle((be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).type_.name()) << '\n'; #endif if( with_what && se ) tmp << "std::exception::what: " << wh << '\n'; diff --git a/include/boost/exception/errinfo_nested_exception.hpp b/include/boost/exception/errinfo_nested_exception.hpp index de055e0..e4e75d9 100644 --- a/include/boost/exception/errinfo_nested_exception.hpp +++ b/include/boost/exception/errinfo_nested_exception.hpp @@ -9,8 +9,10 @@ namespace boost { + namespace exception_detail { class clone_base; }; template class error_info; - class exception_ptr; + template class shared_ptr; + typedef shared_ptr exception_ptr; typedef error_info errinfo_nested_exception; } diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp index 79b2739..fd516dd 100644 --- a/include/boost/exception/exception.hpp +++ b/include/boost/exception/exception.hpp @@ -132,18 +132,6 @@ boost } }; - template - E const & operator<<( E const &, error_info const & ); - - template - E const & operator<<( E const &, throw_function const & ); - - template - E const & operator<<( E const &, throw_file const & ); - - template - E const & operator<<( E const &, throw_line const & ); - class exception; template @@ -163,6 +151,7 @@ boost virtual void set( shared_ptr const &, type_info_ const & ) = 0; virtual void add_ref() const = 0; virtual void release() const = 0; + virtual refcount_ptr clone() const = 0; protected: @@ -184,6 +173,20 @@ boost struct get_info; char const * get_diagnostic_information( exception const &, char const * ); + + void copy_boost_exception( exception *, exception const * ); + + template + E const & set_info( E const &, error_info const & ); + + template + E const & set_info( E const &, throw_function const & ); + + template + E const & set_info( E const &, throw_file const & ); + + template + E const & set_info( E const &, throw_line const & ); } class @@ -216,30 +219,31 @@ boost #endif ; -#if defined(__MWERKS__) && __MWERKS__<=0x3207 +#if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310) public: #else private: template - friend E const & operator<<( E const &, throw_function const & ); + friend E const & exception_detail::set_info( E const &, throw_function const & ); template - friend E const & operator<<( E const &, throw_file const & ); + friend E const & exception_detail::set_info( E const &, throw_file const & ); template - friend E const & operator<<( E const &, throw_line const & ); - - friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); + friend E const & exception_detail::set_info( E const &, throw_line const & ); template - friend E const & operator<<( E const &, error_info const & ); + friend E const & exception_detail::set_info( E const &, error_info const & ); + + friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); template friend struct exception_detail::get_info; friend struct exception_detail::get_info; friend struct exception_detail::get_info; friend struct exception_detail::get_info; + friend void exception_detail::copy_boost_exception( exception *, exception const * ); #endif mutable exception_detail::refcount_ptr data_; mutable char const * throw_function_; @@ -253,28 +257,32 @@ boost { } - template - E const & - operator<<( E const & x, throw_function const & y ) + namespace + exception_detail { - x.throw_function_=y.v_; - return x; - } + template + E const & + set_info( E const & x, throw_function const & y ) + { + x.throw_function_=y.v_; + return x; + } - template - E const & - operator<<( E const & x, throw_file const & y ) - { - x.throw_file_=y.v_; - return x; - } + template + E const & + set_info( E const & x, throw_file const & y ) + { + x.throw_file_=y.v_; + return x; + } - template - E const & - operator<<( E const & x, throw_line const & y ) - { - x.throw_line_=y.v_; - return x; + template + E const & + set_info( E const & x, throw_line const & y ) + { + x.throw_line_=y.v_; + return x; + } } //////////////////////////////////////////////////////////////////////// @@ -300,10 +308,10 @@ boost }; struct large_size { char c[256]; }; - large_size dispatch( exception * ); + large_size dispatch_boost_exception( exception const * ); struct small_size { }; - small_size dispatch( void * ); + small_size dispatch_boost_exception( void const * ); template struct enable_error_info_helper; @@ -326,7 +334,7 @@ boost struct enable_error_info_return_type { - typedef typename enable_error_info_helper::type type; + typedef typename enable_error_info_helper::type type; }; } @@ -363,7 +371,13 @@ boost void copy_boost_exception( exception * a, exception const * b ) { - *a = *b; + refcount_ptr data; + if( error_info_container * d=b->data_.get() ) + data = d->clone(); + a->throw_file_ = b->throw_file_; + a->throw_line_ = b->throw_line_; + a->throw_function_ = b->throw_function_; + a->data_ = data; } inline diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp index cbbc2c0..7aeeee5 100644 --- a/include/boost/exception/info.hpp +++ b/include/boost/exception/info.hpp @@ -1,4 +1,4 @@ -//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. +//Copyright (c) 2006-2010 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) @@ -47,7 +47,7 @@ boost template inline - char const * + std::string error_info:: tag_typeid_name() const { @@ -131,6 +131,9 @@ boost mutable std::string diagnostic_info_str_; mutable int count_; + error_info_container_impl( error_info_container_impl const & ); + error_info_container_impl & operator=( error_info_container const & ); + void add_ref() const { @@ -143,21 +146,46 @@ boost if( !--count_ ) delete this; } + + refcount_ptr + clone() const + { + refcount_ptr p; + error_info_container_impl * c=new error_info_container_impl; + p.adopt(c); + c->info_ = info_; + return p; + } + }; + + template + inline + E const & + set_info( E const & x, error_info const & v ) + { + typedef error_info error_info_tag_t; + shared_ptr p( new error_info_tag_t(v) ); + exception_detail::error_info_container * c=x.data_.get(); + if( !c ) + x.data_.adopt(c=new exception_detail::error_info_container_impl); + c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); + return x; + } + + template + struct + derives_boost_exception + { + enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) }; }; } template inline - E const & + typename enable_if,E const &>::type operator<<( E const & x, error_info const & v ) { - typedef error_info error_info_tag_t; - shared_ptr p( new error_info_tag_t(v) ); - exception_detail::error_info_container * c=x.data_.get(); - if( !c ) - 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 exception_detail::set_info(x,v); } } diff --git a/include/boost/throw_exception.hpp b/include/boost/throw_exception.hpp index 656b8de..1d018c5 100644 --- a/include/boost/throw_exception.hpp +++ b/include/boost/throw_exception.hpp @@ -36,16 +36,32 @@ #if !defined( BOOST_EXCEPTION_DISABLE ) # include # include -# 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(__LINE__)) +# define BOOST_THROW_EXCEPTION(x) ::boost::exception_detail::throw_exception_(x,BOOST_CURRENT_FUNCTION,__FILE__,__LINE__) #else # define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x) #endif namespace boost { +#if !defined( BOOST_EXCEPTION_DISABLE ) + namespace + exception_detail + { + template + void + throw_exception_( E const & x, char const * current_function, char const * file, int line ) + { + throw_exception( + set_info( + set_info( + set_info( + enable_error_info(x), + throw_function(current_function)), + throw_file(file)), + throw_line(line))); + } + } +#endif #ifdef BOOST_NO_EXCEPTIONS diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 996bea6..0d45c2f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,7 +24,7 @@ run 2-throw_exception_no_exceptions_test.cpp ; run 3-throw_exception_no_integration_test.cpp ; run 4-throw_exception_no_both_test.cpp ; run cloning_test.cpp ; -run copy_exception_test.cpp ; +run copy_exception_test.cpp /boost//thread : : : multi ; run unknown_exception_test.cpp ; run exception_test.cpp ; run enable_error_info_test.cpp helper1.cpp ; @@ -36,6 +36,7 @@ run refcount_ptr_test.cpp ; run current_exception_cast_test.cpp ; run no_exceptions_test.cpp : : : off ; run errinfos_test.cpp ; +run exception_ptr_test.cpp /boost//thread : : : multi ; compile-fail exception_fail.cpp ; compile-fail throw_exception_fail.cpp ; compile-fail error_info_const_fail.cpp ; diff --git a/test/copy_exception_test.cpp b/test/copy_exception_test.cpp index 236a610..84974ce 100644 --- a/test/copy_exception_test.cpp +++ b/test/copy_exception_test.cpp @@ -4,25 +4,106 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include #include +typedef boost::error_info answer; + struct -test_exception: - std::exception +err: + virtual boost::exception, + virtual std::exception { }; -int -main() +class +future { - boost::exception_ptr p = boost::copy_exception(test_exception()); + public: + + future (): + ready_ (false) + { + } + + void + set_exception( boost::exception_ptr const & e ) + { + boost::unique_lock lck (mux_); + exc_ = e; + ready_ = true; + cond_.notify_all(); + } + + void + get_exception() const + { + boost::unique_lock lck (mux_); + while (! ready_) + cond_.wait (lck); + rethrow_exception (exc_); + } + + private: + + bool ready_; + boost::exception_ptr exc_; + mutable boost::mutex mux_; + mutable boost::condition_variable cond_; + }; + +void +producer( future & f ) + { + f.set_exception (boost::copy_exception (err () << answer(42))); + } + +void +consumer() + { + future f; + boost::thread thr (boost::bind (&producer, boost::ref (f))); + try + { + f.get_exception (); + } + catch( + err & e ) + { + int const * ans=boost::get_error_info(e); + BOOST_TEST(ans && *ans==42); + } + thr.join(); + } + +void +consume() + { + for( int i=0; i!=100; ++i ) + consumer(); + } + +void +thread_test() + { + boost::thread_group grp; + for( int i=0; i!=50; ++i ) + grp.create_thread(&consume); + grp.join_all (); + } + +void +simple_test() + { + boost::exception_ptr p = boost::copy_exception(err()); try { rethrow_exception(p); BOOST_TEST(false); } catch( - test_exception & ) + err & ) { } catch( @@ -30,5 +111,12 @@ main() { BOOST_TEST(false); } + } + +int +main() + { + simple_test(); + thread_test(); return boost::report_errors(); } diff --git a/test/errinfos_test.cpp b/test/errinfos_test.cpp index c8db595..bf3ad5f 100644 --- a/test/errinfos_test.cpp +++ b/test/errinfos_test.cpp @@ -34,7 +34,7 @@ main() e << errinfo_api_function("failed_api_function") << errinfo_at_line(42) << - errinfo_errno(errno) << + errinfo_errno(0) << errinfo_file_handle(weak_ptr()) << errinfo_file_name("filename.txt") << errinfo_file_open_mode("rb"); diff --git a/test/error_info_test.cpp b/test/error_info_test.cpp index d152caa..53a6d12 100644 --- a/test/error_info_test.cpp +++ b/test/error_info_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -302,7 +303,7 @@ test_add_tuple() } void -test_lifetime() +test_lifetime1() { int count=0; try @@ -323,6 +324,19 @@ test_lifetime() BOOST_TEST(!count); } +void +test_lifetime2() + { + int count=0; + { + boost::exception_ptr ep; + test_exception e; e<0); + } + BOOST_TEST(!count); + } + bool is_const( int const * ) { @@ -354,7 +368,8 @@ main() test_basic_throw_catch(); test_catch_add_info(); test_add_tuple(); - test_lifetime(); + test_lifetime1(); + test_lifetime2(); test_const(); return boost::report_errors(); } diff --git a/test/exception_ptr_test.cpp b/test/exception_ptr_test.cpp new file mode 100644 index 0000000..1da2713 --- /dev/null +++ b/test/exception_ptr_test.cpp @@ -0,0 +1,112 @@ +//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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class thread_handle; +boost::shared_ptr create_thread( boost::function const & f ); +void join( thread_handle & t ); + +class +thread_handle + { + thread_handle( thread_handle const & ); + thread_handle & operator=( thread_handle const & ); + + boost::exception_ptr err_; + boost::thread t_; + + static + void + thread_wrapper( boost::function const & f, boost::exception_ptr & ep ) + { + BOOST_ASSERT(!ep); + try + { + f(); + } + catch(...) + { + ep = boost::current_exception(); + } + } + + explicit + thread_handle( boost::function const & f ): + t_(boost::bind(thread_wrapper,f,err_)) + { + } + + friend boost::shared_ptr create_thread( boost::function const & f ); + friend void join( thread_handle & t ); + }; + +boost::shared_ptr +create_thread( boost::function const & f ) + { + boost::shared_ptr t( new thread_handle(f) ); + return t; + } + +void +join( thread_handle & t ) + { + t.t_.join(); + if( t.err_ ) + rethrow_exception(t.err_); + } + +struct exc: boost::exception, std::exception { }; +typedef boost::error_info answer; + +void +thread_func() + { + BOOST_THROW_EXCEPTION(exc() << answer(42)); + } + +void +check( boost::shared_ptr const & t ) + { + try + { + join(*t); + } + catch( + exc & e ) + { + int const * a = boost::get_error_info(e); + BOOST_TEST(a && *a==42); + } + } + +int +main() + { + try + { + std::vector< boost::shared_ptr > threads; + std::generate_n(std::inserter(threads,threads.end()),256,boost::bind(create_thread,thread_func)); + std::for_each(threads.begin(),threads.end(),check); + return boost::report_errors(); + } + catch( + ... ) + { + std::cerr << + "Caught unexpected exception.\n" + "Output from current_exception_diagnostic_information:\n" << + boost::current_exception_diagnostic_information() << std::endl; + return 42; + } + } diff --git a/test/is_output_streamable_test.cpp b/test/is_output_streamable_test.cpp index cb030b7..963989f 100644 --- a/test/is_output_streamable_test.cpp +++ b/test/is_output_streamable_test.cpp @@ -4,7 +4,6 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include -#include namespace n1 @@ -31,11 +30,20 @@ n2 } } +template +struct test; + +template <> +struct +test + { + }; + int main() { - BOOST_TEST( !boost::is_output_streamable::value ); - BOOST_TEST( boost::is_output_streamable::value ); - BOOST_TEST( boost::is_output_streamable::value ); - return boost::report_errors(); + test::value>(); + test::value>(); + test::value>(); + return 0; }