$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81111 - in trunk: boost/thread boost/thread/detail libs/thread/example libs/thread/test libs/thread/test/sync/futures/async libs/thread/test/sync/futures/future
From: vicente.botet_at_[hidden]
Date: 2012-10-30 05:36:25
Author: viboes
Date: 2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
New Revision: 81111
URL: http://svn.boost.org/trac/boost/changeset/81111
Log:
Thread: remove some rvalue-references limitations for future::then and make_shared.
Added:
   trunk/libs/thread/test/sync/futures/future/then_pass.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/thread/detail/config.hpp                     |     3 -                                       
   trunk/boost/thread/future.hpp                            |   113 +++++++++++++++++++++++++++++++++------ 
   trunk/libs/thread/example/make_future.cpp                |     8 --                                      
   trunk/libs/thread/test/Jamfile.v2                        |    14 ++--                                    
   trunk/libs/thread/test/sync/futures/async/async_pass.cpp |     4                                         
   5 files changed, 105 insertions(+), 37 deletions(-)
Modified: trunk/boost/thread/detail/config.hpp
==============================================================================
--- trunk/boost/thread/detail/config.hpp	(original)
+++ trunk/boost/thread/detail/config.hpp	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -186,11 +186,8 @@
 // FUTURE_CONTINUATION
 #if ! defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \
  && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CONTINUATION
-
-#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
 #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
 #endif
-#endif
 
 // FUTURE_INVALID_AFTER_GET
 #if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \
Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp	(original)
+++ trunk/boost/thread/future.hpp	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -525,6 +525,7 @@
 
         };
 
+        // Used to create stand-alone futures
         template<typename T>
         struct future_object:
             detail::future_object_base
@@ -1045,11 +1046,16 @@
 #endif
 
 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+
 //        template<typename F>
 //        auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
-        template<typename F>
-        inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type> then(F&& func);
 
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+        template<typename RF>
+        inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
+#endif
+        template<typename F>
+        inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type> then(BOOST_THREAD_RV_REF(F) func);
 #endif
     };
 
@@ -2135,11 +2141,15 @@
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
   #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
         template <class F, class ...ArgTypes>
-        BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+        BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+            typename decay<ArgTypes>::type...
+        )>::type>
         async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
         {
 
-          typedef typename boost::result_of<typename decay<F>::type()>::type R;
+          typedef typename boost::result_of<typename decay<F>::type(
+              typename decay<ArgTypes>::type...
+          )>::type R;
           typedef packaged_task<R(ArgTypes...)> packaged_task_type;
   #else
         template <class F>
@@ -2192,11 +2202,16 @@
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
   #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
         template <class F, class ...ArgTypes>
-        BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+        BOOST_THREAD_FUTURE<typename boost::result_of<
+          typename decay<F>::type()>::type(
+              typename decay<ArgTypes>::type...
+          )>
         async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
         {
 
-          typedef typename boost::result_of<typename decay<F>::type()>::type R;
+          typedef typename boost::result_of<typename decay<F>::type(
+              typename decay<ArgTypes>::type...
+              )>::type R;
           typedef packaged_task<R(ArgTypes...)> packaged_task_type;
   #else
         template <class F>
@@ -2241,7 +2256,7 @@
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
   #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
         template <class F, class ...ArgTypes>
-        BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+        BOOST_THREAD_FUTURE<typename boost::result_of<F(typename decay<ArgTypes>::type...)>::type>
         async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args )
         {
             return async(launch::any, boost::forward<F>(f), boost::forward<ArgTypes>(args)...);
@@ -2265,26 +2280,25 @@
 
 #endif
 
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
   template <typename T>
-  BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(T&& value)
+  BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
   {
     typedef typename decay<T>::type future_type;
     promise<future_type> p;
-    p.set_value(value);
-    return boost::move(p.get_future());
+    p.set_value(boost::forward<T>(value));
+    return p.get_future();
   }
 
 
   inline BOOST_THREAD_FUTURE<void> make_future()
   {
     promise<void> p;
-    return boost::move(p.get_future());
+    return p.get_future();
 
   }
 
   template <typename T>
-  shared_future<typename decay<T>::type> make_shared_future(T&& value)
+  shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
   {
     typedef typename decay<T>::type future_type;
     promise<future_type> p;
@@ -2299,12 +2313,10 @@
     return p.get_future().share();
 
   }
-#endif
 
 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
   namespace detail
   {
-
       template <typename F, typename R, typename C>
       struct future_continuation : future_continuation_base
       {
@@ -2312,7 +2324,10 @@
         C continuation;
         promise<R> next;
 
-        future_continuation(F& f, C&& c) : parent(f), continuation(boost::forward<C>(c)), next()
+        future_continuation(F& f, BOOST_THREAD_FWD_REF(C) c) :
+          parent(f),
+          continuation(boost::forward<C>(c)),
+          next()
         {}
         ~future_continuation()
         {}
@@ -2335,14 +2350,50 @@
         future_continuation(future_continuation const&);
         future_continuation& operator=(future_continuation const&);
       };
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+      template <typename F, typename R, typename CR>
+      struct future_continuation<F,R,CR(*)(F&)> : future_continuation_base
+      {
+        F& parent;
+        CR(*continuation)(F&) ;
+        promise<R> next;
+
+        future_continuation(F& f, CR(*c)(F&)) :
+          parent(f),
+          continuation(c),
+          next()
+        {}
+        ~future_continuation()
+        {}
+
+        void do_continuation(boost::unique_lock<boost::mutex>& lk)
+        {
+          try
+          {
+            lk.unlock();
+            R val = continuation(parent);
+            next.set_value(boost::move(val));
+          }
+          catch (...)
+          {
+            next.set_exception(boost::current_exception());
+          }
+        }
+      private:
+
+        future_continuation(future_continuation const&);
+        future_continuation& operator=(future_continuation const&);
+      };
+#endif
   }
 
 //        template<typename F>
 //        auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+
   template <typename R>
   template <typename F>
   inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type>
-  BOOST_THREAD_FUTURE<R>::then(F&& func)
+  BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_RV_REF(F) func)
   {
 
     typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
@@ -2363,6 +2414,34 @@
     }
 
   }
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+  template <typename R>
+  template<typename RF>
+  BOOST_THREAD_FUTURE<RF>
+  BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&))
+  {
+
+    typedef RF future_type;
+
+    if (future_)
+    {
+      boost::unique_lock<boost::mutex> lock(future_->mutex);
+      detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
+          new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func);
+      if (ptr==0)
+      {
+        return BOOST_THREAD_FUTURE<future_type>();
+      }
+      future_->set_continuation_ptr(ptr, lock);
+      return ptr->next.get_future();
+    } else {
+      return BOOST_THREAD_FUTURE<future_type>();
+    }
+
+  }
+#endif
+
 #endif
 
 }
Modified: trunk/libs/thread/example/make_future.cpp
==============================================================================
--- trunk/libs/thread/example/make_future.cpp	(original)
+++ trunk/libs/thread/example/make_future.cpp	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -7,7 +7,6 @@
 
 #include <boost/thread/future.hpp>
 #include <iostream>
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 
 int p1() { return 5; }
 
@@ -41,10 +40,3 @@
   }
   return 0;
 }
-#else
-
-int main()
-{
-  return 0;
-}
-#endif
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2	(original)
+++ trunk/libs/thread/test/Jamfile.v2	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -204,6 +204,7 @@
           [ thread-run test_6174.cpp ]
           [ thread-run test_7160.cpp ]
           [ thread-run test_7328.cpp ]
+          [ thread-run test_7571.cpp ]
     ;
 
 
@@ -524,6 +525,11 @@
           #[ thread-run ../example/vhh_shared_mutex.cpp ]
           [ thread-run ../example/make_future.cpp ]
           [ thread-run ../example/future_then.cpp ]
+          [ thread-run ../example/synchronized_value.cpp ]
+          [ thread-run ../example/thread_guard.cpp ]
+          [ thread-run ../example/scoped_thread.cpp ]
+          [ thread-run ../example/strict_lock.cpp ]
+          [ thread-run ../example/ba_externallly_locked.cpp ]
 
     ;
 
@@ -559,16 +565,10 @@
           [ thread-run2 ./sync/mutual_exclusion/locks/reverse_lock/types_pass.cpp : reverse_lock__types_p ]
     ;
 
-    #explicit ts_ ;
+    explicit ts_ ;
     test-suite ts_
     :
-          [ thread-run ../example/strict_lock.cpp ]
           #[ thread-run ../example/unwrap.cpp ]
-          [ thread-run ../example/synchronized_value.cpp ]
-          [ thread-run ../example/thread_guard.cpp ]
-          [ thread-run ../example/scoped_thread.cpp ]
-          [ thread-run ../example/ba_externallly_locked.cpp ]
-          [ thread-run test_7571.cpp ]
     ;
 
 }
Modified: trunk/libs/thread/test/sync/futures/async/async_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/async/async_pass.cpp	(original)
+++ trunk/libs/thread/test/sync/futures/async/async_pass.cpp	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -39,7 +39,7 @@
     long data_;
 
 public:
-    typedef int result_type;
+    typedef long result_type;
 
     explicit A(long i) : data_(i) {}
 
@@ -122,7 +122,7 @@
     BOOST_TEST(t1 - t0 < ms(100));
   }
   {
-    boost::future<int> f = boost::async(boost::launch::async, A(3));
+    boost::future<long> f = boost::async(boost::launch::async, A(3));
     boost::this_thread::sleep_for(ms(300));
     Clock::time_point t0 = Clock::now();
     BOOST_TEST(f.get() == 3);
Added: trunk/libs/thread/test/sync/futures/future/then_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/future/then_pass.cpp	2012-10-30 05:36:22 EDT (Tue, 30 Oct 2012)
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2011 Vicente J. Botet Escriba
+//
+//  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)
+
+// <boost/thread/future.hpp>
+
+// class future<R>
+
+// template<typename F>
+// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+
+int p1()
+{
+  return 1;
+}
+
+int p2(boost::future<int>& f)
+{
+  return 2 * f.get();
+}
+
+int main()
+{
+  {
+    boost::future<int> f1 = boost::async(p1);
+    boost::future<int> f2 = f1.then(p2);
+    BOOST_TEST(f2.get()==2);
+  }
+  {
+    boost::future<int> f1 = boost::async(p1);
+    boost::future<int> f2 = f1.then(p2).then(p2);
+    BOOST_TEST(f2.get()==4);
+  }
+
+  return boost::report_errors();
+}
+
+#else
+
+int main()
+{
+  return 0;
+}
+#endif