$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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;
+        }
     }