|
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