Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r59364 - in trunk: boost/exception boost/exception/detail libs/exception/test
From: emil_at_[hidden]
Date: 2010-01-30 00:26:45


Author: emildotchevski
Date: 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
New Revision: 59364
URL: http://svn.boost.org/trac/boost/changeset/59364

Log:
Ticket #3848 (thanks Nikki Chumakov) and (unrelated) exception_ptr refactoring.
Text files modified:
   trunk/boost/exception/detail/exception_ptr.hpp | 131 ++++++++++++-------------------------
   trunk/boost/exception/errinfo_nested_exception.hpp | 4
   trunk/boost/exception/exception.hpp | 12 +++
   trunk/boost/exception/info.hpp | 8 ++
   trunk/libs/exception/test/Jamfile.v2 | 2
   trunk/libs/exception/test/copy_exception_test.cpp | 100 +++++++++++++++++++++++++++-
   trunk/libs/exception/test/exception_ptr_test.cpp | 136 ++++++++++++++++++++--------------------
   7 files changed, 229 insertions(+), 164 deletions(-)

Modified: trunk/boost/exception/detail/exception_ptr.hpp
==============================================================================
--- trunk/boost/exception/detail/exception_ptr.hpp (original)
+++ trunk/boost/exception/detail/exception_ptr.hpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -28,6 +28,8 @@
 namespace
 boost
     {
+ typedef shared_ptr<exception_detail::clone_base const> exception_ptr;
+
 #ifndef BOOST_NO_RTTI
     typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type;
 
@@ -39,85 +41,34 @@
         }
 #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<exception_detail::clone_base const> c_;
- bool bad_alloc_;
-
- struct
- bad_alloc_tag
- {
- };
-
- explicit
- exception_ptr( bad_alloc_tag ):
- bad_alloc_(true)
- {
- }
-
- explicit
- exception_ptr( shared_ptr<exception_detail::clone_base const> 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);
+ inline
+ static
+ exception_ptr
+ exception_ptr_bad_alloc()
+ {
+ static
+ struct
+ bad_alloc_:
+ std::bad_alloc,
+ exception_detail::clone_base
+ {
+ clone_base const *
+ clone() const
+ {
+ return new bad_alloc_(*this);
+ }
+ void
+ rethrow() const
+ {
+ throw*this;
+ }
+ } e;
+ return exception_ptr(exception_ptr(),&e);
             }
- };
+ }
 
     class
     unknown_exception:
@@ -256,7 +207,7 @@
 
         template <class T>
         inline
- shared_ptr<clone_base const>
+ exception_ptr
         current_exception_std_exception( T const & e1 )
             {
             if( boost::exception const * e2 = get_boost_exception(&e1) )
@@ -266,21 +217,21 @@
             }
 
         inline
- shared_ptr<clone_base const>
+ exception_ptr
         current_exception_unknown_exception()
             {
             return shared_ptr<unknown_exception const>(new unknown_exception());
             }
 
         inline
- shared_ptr<clone_base const>
+ exception_ptr
         current_exception_unknown_boost_exception( boost::exception const & e )
             {
             return shared_ptr<unknown_exception const>(new unknown_exception(e));
             }
 
         inline
- shared_ptr<clone_base const>
+ exception_ptr
         current_exception_unknown_std_exception( std::exception const & e )
             {
             if( boost::exception const * be = get_boost_exception(&e) )
@@ -290,7 +241,7 @@
             }
 
         inline
- shared_ptr<clone_base const>
+ exception_ptr
         current_exception_impl()
             {
             try
@@ -300,7 +251,7 @@
             catch(
             exception_detail::clone_base & e )
                 {
- return shared_ptr<exception_detail::clone_base const>(e.clone());
+ return exception_ptr(e.clone());
                 }
             catch(
             std::domain_error & e )
@@ -396,24 +347,28 @@
     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();
             }
         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();
                 }
             catch(
             ... )
@@ -421,7 +376,8 @@
                 BOOST_ASSERT(0);
                 }
             }
- return exception_ptr(exception_ptr::bad_alloc_tag());
+ BOOST_ASSERT(ret);
+ return ret;
         }
 
     template <class T>
@@ -444,7 +400,8 @@
     void
     rethrow_exception( exception_ptr const & p )
         {
- p.rethrow();
+ BOOST_ASSERT(p);
+ p->rethrow();
         }
 
     inline

Modified: trunk/boost/exception/errinfo_nested_exception.hpp
==============================================================================
--- trunk/boost/exception/errinfo_nested_exception.hpp (original)
+++ trunk/boost/exception/errinfo_nested_exception.hpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -9,8 +9,10 @@
 namespace
 boost
     {
+ namespace exception_detail { class clone_base; };
     template <class Tag,class T> class error_info;
- class exception_ptr;
+ template <class T> class shared_ptr;
+ typedef shared_ptr<exception_detail::clone_base const> exception_ptr;
     typedef error_info<struct errinfo_nested_exception_,exception_ptr> errinfo_nested_exception;
     }
 

Modified: trunk/boost/exception/exception.hpp
==============================================================================
--- trunk/boost/exception/exception.hpp (original)
+++ trunk/boost/exception/exception.hpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -163,6 +163,7 @@
             virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0;
             virtual void add_ref() const = 0;
             virtual void release() const = 0;
+ virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0;
 
             protected:
 
@@ -184,6 +185,8 @@
         struct get_info<throw_line>;
 
         char const * get_diagnostic_information( exception const &, char const * );
+
+ void copy_boost_exception( exception *, exception const * );
         }
 
     class
@@ -240,6 +243,7 @@
         friend struct exception_detail::get_info<throw_function>;
         friend struct exception_detail::get_info<throw_file>;
         friend struct exception_detail::get_info<throw_line>;
+ friend void exception_detail::copy_boost_exception( exception *, exception const * );
 #endif
         mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
         mutable char const * throw_function_;
@@ -363,7 +367,13 @@
         void
         copy_boost_exception( exception * a, exception const * b )
             {
- *a = *b;
+ refcount_ptr<error_info_container> 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

Modified: trunk/boost/exception/info.hpp
==============================================================================
--- trunk/boost/exception/info.hpp (original)
+++ trunk/boost/exception/info.hpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -143,6 +143,14 @@
                 if( !--count_ )
                     delete this;
                 }
+
+ refcount_ptr<exception_detail::error_info_container>
+ clone() const
+ {
+ refcount_ptr<exception_detail::error_info_container> c;
+ c.adopt(new exception_detail::error_info_container_impl(*this));
+ return c;
+ }
             };
         }
 

Modified: trunk/libs/exception/test/Jamfile.v2
==============================================================================
--- trunk/libs/exception/test/Jamfile.v2 (original)
+++ trunk/libs/exception/test/Jamfile.v2 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -24,7 +24,7 @@
 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 : : : <threading>multi ;
 run unknown_exception_test.cpp ;
 run exception_test.cpp ;
 run enable_error_info_test.cpp helper1.cpp ;

Modified: trunk/libs/exception/test/copy_exception_test.cpp
==============================================================================
--- trunk/libs/exception/test/copy_exception_test.cpp (original)
+++ trunk/libs/exception/test/copy_exception_test.cpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -4,25 +4,106 @@
 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
 #include <boost/exception_ptr.hpp>
+#include <boost/exception/get_error_info.hpp>
+#include <boost/thread.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
+typedef boost::error_info<struct tag_answer,int> answer;
+
 struct
-test_exception:
- std::exception
+err:
+ virtual boost::exception,
+ virtual std::exception
     {
     };
 
-int
-main()
+class
+future
+ {
+ public:
+
+ future ():
+ ready_ (false)
+ {
+ }
+
+ void
+ set_exception( boost::exception_ptr const & e )
+ {
+ boost::unique_lock<boost::mutex> lck (mux_);
+ exc_ = e;
+ ready_ = true;
+ cond_.notify_all();
+ }
+
+ void
+ get_exception() const
+ {
+ boost::unique_lock<boost::mutex> 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()
     {
- boost::exception_ptr p = boost::copy_exception(test_exception());
+ 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<answer>(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 @@
         {
         BOOST_TEST(false);
         }
+ }
+
+int
+main()
+ {
+ simple_test();
+ thread_test();
     return boost::report_errors();
     }

Modified: trunk/libs/exception/test/exception_ptr_test.cpp
==============================================================================
--- trunk/libs/exception/test/exception_ptr_test.cpp (original)
+++ trunk/libs/exception/test/exception_ptr_test.cpp 2010-01-30 00:26:43 EST (Sat, 30 Jan 2010)
@@ -18,91 +18,91 @@
 
 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<void()> const & f, boost::exception_ptr & ep )
- {
- BOOST_ASSERT(!ep);
- try
- {
- f();
- }
- catch(...)
- {
- ep = boost::current_exception();
- }
- }
-
- explicit
- thread_handle( boost::function<void()> const & f ):
- t_(boost::bind(thread_wrapper,f,err_))
- {
- }
-
- friend boost::shared_ptr<thread_handle> create_thread( boost::function<void()> const & f );
- friend void join( thread_handle & t );
- };
+ {
+ thread_handle( thread_handle const & );
+ thread_handle & operator=( thread_handle const & );
+
+ boost::exception_ptr err_;
+ boost::thread t_;
+
+ static
+ void
+ thread_wrapper( boost::function<void()> const & f, boost::exception_ptr & ep )
+ {
+ BOOST_ASSERT(!ep);
+ try
+ {
+ f();
+ }
+ catch(...)
+ {
+ ep = boost::current_exception();
+ }
+ }
+
+ explicit
+ thread_handle( boost::function<void()> const & f ):
+ t_(boost::bind(thread_wrapper,f,err_))
+ {
+ }
+
+ friend boost::shared_ptr<thread_handle> create_thread( boost::function<void()> const & f );
+ friend void join( thread_handle & t );
+ };
 
 boost::shared_ptr<thread_handle>
 create_thread( boost::function<void()> const & f )
- {
- boost::shared_ptr<thread_handle> t( new thread_handle(f) );
- return t;
- }
+ {
+ boost::shared_ptr<thread_handle> t( new thread_handle(f) );
+ return t;
+ }
 
 void
 join( thread_handle & t )
- {
- t.t_.join();
- if( t.err_ )
- rethrow_exception(t.err_);
- }
+ {
+ t.t_.join();
+ if( t.err_ )
+ rethrow_exception(t.err_);
+ }
 
 struct exc: boost::exception, std::exception { };
 typedef boost::error_info<struct answer_,int> answer;
 
 void
 thread_func()
- {
- BOOST_THROW_EXCEPTION(exc() << answer(42));
- }
+ {
+ BOOST_THROW_EXCEPTION(exc() << answer(42));
+ }
 
 void
 check( boost::shared_ptr<thread_handle> const & t )
- {
- try
- {
- join(*t);
- }
- catch(
- exc & e )
- {
- int const * a = boost::get_error_info<answer>(e);
- BOOST_TEST(a && *a==42);
- }
- }
+ {
+ try
+ {
+ join(*t);
+ }
+ catch(
+ exc & e )
+ {
+ int const * a = boost::get_error_info<answer>(e);
+ BOOST_TEST(a && *a==42);
+ }
+ }
 
 int
 main()
     {
- try
- {
- std::vector< boost::shared_ptr<thread_handle> > 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(
- ... )
- {
- BOOST_ERROR(boost::current_exception_diagnostic_information().c_str());
- return 42;
- }
+ try
+ {
+ std::vector< boost::shared_ptr<thread_handle> > 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(
+ ... )
+ {
+ BOOST_ERROR(boost::current_exception_diagnostic_information().c_str());
+ return 42;
+ }
     }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk