Boost logo

Boost-Commit :

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


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