$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84685 - in trunk: boost/thread libs/thread/test/sync/futures/future libs/thread/test/sync/futures/promise libs/thread/test/sync/futures/shared_future
From: vicente.botet_at_[hidden]
Date: 2013-06-08 06:53:46
Author: viboes
Date: 2013-06-08 06:53:46 EDT (Sat, 08 Jun 2013)
New Revision: 84685
URL: http://svn.boost.org/trac/boost/changeset/84685
Log:
Thread: fix bug on future::then when the continuation is void() ir T&().
Text files modified: 
   trunk/boost/thread/future.hpp                                   |   104 ++++++++++++++++++++++----------------- 
   trunk/libs/thread/test/sync/futures/future/then_pass.cpp        |    34 ++++++++++++                            
   trunk/libs/thread/test/sync/futures/promise/default_pass.cpp    |     2                                         
   trunk/libs/thread/test/sync/futures/shared_future/then_pass.cpp |    33 ++++++++++++                            
   4 files changed, 124 insertions(+), 49 deletions(-)
Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp	Sat Jun  8 04:21:34 2013	(r84684)
+++ trunk/boost/thread/future.hpp	2013-06-08 06:53:46 EDT (Sat, 08 Jun 2013)	(r84685)
@@ -3467,7 +3467,7 @@
       Fp continuation;
 
     public:
-      explicit future_async_continuation_shared_state(
+      future_async_continuation_shared_state(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
       parent(f.future_),
@@ -3503,14 +3503,14 @@
     template<typename F, typename Fp>
     struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
     {
-      F& parent;
+      F parent;
       Fp continuation;
 
     public:
-      explicit future_async_continuation_shared_state(
+      future_async_continuation_shared_state(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
-      parent(f),
+            parent(f.future_),
       //continuation(boost::forward<Fp>(c)
       continuation(boost::move(c))
       {
@@ -3549,14 +3549,14 @@
     template<typename F, typename Rp, typename Fp>
     struct future_deferred_continuation_shared_state: shared_state<Rp>
     {
-      F& parent;
+      F parent;
       Fp continuation;
 
     public:
-      explicit future_deferred_continuation_shared_state(
+      future_deferred_continuation_shared_state(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
-          parent(f),
+          parent(f.future_),
           //continuation(boost::forward<Fp>(c)
           continuation(c)
       {
@@ -3583,14 +3583,14 @@
     template<typename F, typename Fp>
     struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
     {
-      F& parent;
+      F parent;
       Fp continuation;
 
     public:
-      explicit future_deferred_continuation_shared_state(
+      future_deferred_continuation_shared_state(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ):
-          parent(f),
+          parent(f.future_),
           continuation(boost::move(c))
       {
         this->set_deferred();
@@ -3661,12 +3661,6 @@
     typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
     BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
 
-//    if (this->future_==0)
-//    {
-//      // fixme what to do when the future has no associated state?
-//      return BOOST_THREAD_FUTURE<future_type>();
-//    }
-
     boost::unique_lock<boost::mutex> lock(this->future_->mutex);
     if (int(policy) & int(launch::async))
     {
@@ -3682,9 +3676,7 @@
     }
     else
     {
-      // fixme what to do when the policy is invalid?
       BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
-      //return BOOST_THREAD_FUTURE<future_type>();
     }
 
   }
@@ -3697,13 +3689,6 @@
     typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
     BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
 
-//    if (this->future_==0)
-//    {
-//      //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
-//      // fixme what to do when the future has no associated state?
-//      return BOOST_THREAD_FUTURE<future_type>();
-//    }
-
     boost::unique_lock<boost::mutex> lock(this->future_->mutex);
     if (int(this->launch_policy()) & int(launch::async))
     {
@@ -3720,9 +3705,7 @@
     }
     else
     {
-      // fixme what to do when the policy is invalid?
       BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
-      //return BOOST_THREAD_FUTURE<future_type>();
     }
   }
 
@@ -3789,12 +3772,6 @@
     typedef typename boost::result_of<F(shared_future<R>&)>::type future_type;
     BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
 
-//    if (this->future_==0)
-//    {
-//      // fixme what to do when the future has no associated state?
-//      return BOOST_THREAD_FUTURE<future_type>();
-//    }
-
     boost::unique_lock<boost::mutex> lock(this->future_->mutex);
     if (int(policy) & int(launch::async))
     {
@@ -3810,9 +3787,7 @@
     }
     else
     {
-      // fixme what to do when the policy is invalid?
       BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
-      //return BOOST_THREAD_FUTURE<future_type>();
     }
 
   }
@@ -3825,12 +3800,6 @@
     typedef typename boost::result_of<F(shared_future<R>&)>::type future_type;
 
     BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
-//    if (this->future_==0)
-//    {
-//      //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
-//      // fixme what to do when the future has no associated state?
-//      return BOOST_THREAD_FUTURE<future_type>();
-//    }
 
     boost::unique_lock<boost::mutex> lock(this->future_->mutex);
     if (int(this->launch_policy()) & int(launch::async))
@@ -3848,21 +3817,66 @@
     }
     else
     {
-      // fixme what to do when the policy is invalid?
       BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
-      //return BOOST_THREAD_FUTURE<future_type>();
     }
   }
 #endif
 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
   namespace detail
   {
+
+    /////////////////////////
+    /// future_unwrap_shared_state
+    /////////////////////////
+
+    template<typename Rp>
+    struct future_unwrap_shared_state: future_async_shared_state_base<Rp>
+    {
+      typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
+
+      future_ptr parent_;
+    public:
+      explicit future_async_continuation_shared_state(
+          F& f, BOOST_THREAD_FWD_REF(Fp) c
+          ) :
+      parent(f.future_),
+      continuation(c)
+      {
+      }
+
+      void launch_continuation(boost::unique_lock<boost::mutex>& lock)
+      {
+        lock.unlock();
+        this->thr_ = thread(&future_async_continuation_shared_state::run, this);
+      }
+
+      static void run(future_async_continuation_shared_state* that)
+      {
+        try
+        {
+          that->mark_finished_with_result(that->continuation(that->parent));
+        }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+        catch(thread_interrupted& )
+        {
+          that->mark_interrupted_finish();
+        }
+#endif
+        catch(...)
+        {
+          that->mark_exceptional_finish();
+        }
+      }
+    };
+
     template <class Rp>
     typename BOOST_THREAD_FUTURE<Rp>::value_type
     make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_FUTURE<Rp>& f)
     {
-      shared_ptr<future_unwrap_shared_state<Rp> >
-          h(new future_unwrap_shared_state<Rp>(f, boost::forward<Fp>(c)));
+
+      typedef typename BOOST_THREAD_FUTURE<Rp>::value_type future_value_type;
+      shared_ptr<future_unwrap_shared_state<future_value_type> >
+          h(new future_unwrap_shared_state<future_value_type>(f.future_));
       f.future_->set_continuation_ptr(h, lock);
       return BOOST_THREAD_FUTURE<Rp>(h);
     }
Modified: trunk/libs/thread/test/sync/futures/future/then_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/future/then_pass.cpp	Sat Jun  8 04:21:34 2013	(r84684)
+++ trunk/libs/thread/test/sync/futures/future/then_pass.cpp	2013-06-08 06:53:46 EDT (Sat, 08 Jun 2013)	(r84685)
@@ -20,6 +20,7 @@
 
 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
 
+
 int p1()
 {
   BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG;
@@ -38,10 +39,20 @@
   return 2 * i;
 }
 
+void p3(boost::future<int>& f)
+{
+  BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
+  BOOST_TEST(f.valid());
+  int i = f.get();
+  boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+  BOOST_THREAD_LOG << "p3 <" << &f << " " <<i << BOOST_THREAD_END_LOG;
+  return;
+}
+
 int main()
 {
+  BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
   {
-    BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
     boost::future<int> f1 = boost::async(boost::launch::async, &p1);
     BOOST_TEST(f1.valid());
     boost::future<int> f2 = f1.then(&p2);
@@ -63,6 +74,27 @@
   }
   BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
   {
+    boost::future<int> f1 = boost::async(boost::launch::async, &p1);
+    BOOST_TEST(f1.valid());
+    boost::future<void> f2 = f1.then(&p3);
+    BOOST_TEST(f2.valid());
+    try
+    {
+      f2.wait();
+    }
+    catch (std::exception& ex)
+    {
+      BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+      BOOST_TEST(false);
+    }
+    catch (...)
+    {
+      BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+      BOOST_TEST(false);
+    }
+  }
+  BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+  {
     boost::future<int> f2 = boost::async(p1).then(&p2);
     BOOST_TEST(f2.get()==2);
   }
Modified: trunk/libs/thread/test/sync/futures/promise/default_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/promise/default_pass.cpp	Sat Jun  8 04:21:34 2013	(r84684)
+++ trunk/libs/thread/test/sync/futures/promise/default_pass.cpp	2013-06-08 06:53:46 EDT (Sat, 08 Jun 2013)	(r84685)
@@ -38,9 +38,7 @@
   }
   {
       boost::promise<void> p;
-      std::cout << __LINE__ << std::endl;
       boost::future<void> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
-      std::cout << __LINE__ << std::endl;
       BOOST_TEST(f.valid());
   }
 
Modified: trunk/libs/thread/test/sync/futures/shared_future/then_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/shared_future/then_pass.cpp	Sat Jun  8 04:21:34 2013	(r84684)
+++ trunk/libs/thread/test/sync/futures/shared_future/then_pass.cpp	2013-06-08 06:53:46 EDT (Sat, 08 Jun 2013)	(r84685)
@@ -38,10 +38,20 @@
   return 2 * i;
 }
 
+void p3(boost::shared_future<int>& f)
+{
+  BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
+  BOOST_TEST(f.valid());
+  int i = f.get();
+  boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+  BOOST_THREAD_LOG << "p3 <" << &f << " " << i << BOOST_THREAD_END_LOG;
+  return ;
+}
+
 int main()
 {
+  BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
   {
-    BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
     boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
     BOOST_TEST(f1.valid());
     boost::future<int> f2 = f1.then(&p2);
@@ -63,6 +73,27 @@
   }
   BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
   {
+    boost::shared_future<int> f1 = boost::async(boost::launch::async, &p1).share();
+    BOOST_TEST(f1.valid());
+    boost::future<void> f2 = f1.then(&p3);
+    BOOST_TEST(f2.valid());
+    try
+    {
+      f2.wait();
+    }
+    catch (std::exception& ex)
+    {
+      BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
+      BOOST_TEST(false);
+    }
+    catch (...)
+    {
+      BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
+      BOOST_TEST(false);
+    }
+  }
+  BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
+  {
     boost::future<int> f2 = boost::async(p1).share().then(&p2);
     BOOST_TEST(f2.get()==2);
   }