|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83811 - in branches/release: boost/thread boost/thread/detail libs/thread libs/thread/example libs/thread/test libs/thread/test/sync/futures/async libs/thread/test/sync/futures/future libs/thread/test/sync/futures/shared_future libs/thread/test/threads/thread/constr
From: vicente.botet_at_[hidden]
Date: 2013-04-08 13:23:03
Author: viboes
Date: 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
New Revision: 83811
URL: http://svn.boost.org/trac/boost/changeset/83811
Log:
Thread: merge from trunk 1.54: Added lambda tests, refactored future::then, added tests for future::wait...
Added:
branches/release/libs/thread/example/lambda_future.cpp
- copied unchanged from r83800, /trunk/libs/thread/example/lambda_future.cpp
branches/release/libs/thread/test/sync/futures/future/wait_for_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/future/wait_for_pass.cpp
branches/release/libs/thread/test/sync/futures/future/wait_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/future/wait_pass.cpp
branches/release/libs/thread/test/sync/futures/future/wait_until_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/future/wait_until_pass.cpp
branches/release/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/shared_future/wait_for_pass.cpp
branches/release/libs/thread/test/sync/futures/shared_future/wait_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/shared_future/wait_pass.cpp
branches/release/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/sync/futures/shared_future/wait_until_pass.cpp
branches/release/libs/thread/test/threads/thread/constr/lambda_pass.cpp
- copied unchanged from r83800, /trunk/libs/thread/test/threads/thread/constr/lambda_pass.cpp
Properties modified:
branches/release/boost/thread/ (props changed)
branches/release/libs/thread/ (props changed)
Text files modified:
branches/release/boost/thread/detail/config.hpp | 7
branches/release/boost/thread/future.hpp | 1040 ++++++++++++++++++++++++++-------------
branches/release/libs/thread/example/future_then.cpp | 10
branches/release/libs/thread/example/tennis.cpp | 9
branches/release/libs/thread/test/Jamfile.v2 | 42 +
branches/release/libs/thread/test/sync/futures/async/async_pass.cpp | 12
branches/release/libs/thread/test/sync/futures/future/get_pass.cpp | 28
branches/release/libs/thread/test/sync/futures/future/then_pass.cpp | 84 +-
8 files changed, 801 insertions(+), 431 deletions(-)
Modified: branches/release/boost/thread/detail/config.hpp
==============================================================================
--- branches/release/boost/thread/detail/config.hpp (original)
+++ branches/release/boost/thread/detail/config.hpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -158,7 +158,7 @@
// fixme BOOST_THREAD_PROVIDES_ONCE_CXX11 doesn't works when thread.cpp is compiled BOOST_THREAD_VERSION 3
#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \
&& ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11
-#define BOOST_THREAD_PROVIDES_ONCE_CXX11
+#define BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11
#endif
// THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
@@ -371,8 +371,9 @@
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_THREAD_PLATFORM_WIN32)
-# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
- //For compilers supporting auto-tss cleanup
+# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) \
+ || defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32)
+ //For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
Modified: branches/release/boost/thread/future.hpp
==============================================================================
--- branches/release/boost/thread/future.hpp (original)
+++ branches/release/boost/thread/future.hpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -1,5 +1,5 @@
// (C) Copyright 2008-10 Anthony Williams
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+// (C) Copyright 2011-2013 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -67,41 +67,41 @@
namespace boost
{
- //enum class launch
- BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
- {
- none = 0,
- async = 1,
- deferred = 2,
- any = async | deferred
- }
- BOOST_SCOPED_ENUM_DECLARE_END(launch)
+ //enum class launch
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
+ {
+ none = 0,
+ async = 1,
+ deferred = 2,
+ any = async | deferred
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(launch)
- //enum class future_status
- BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
- {
- ready,
- timeout,
- deferred
- }
- BOOST_SCOPED_ENUM_DECLARE_END(future_status)
+ //enum class future_status
+ BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
+ {
+ ready,
+ timeout,
+ deferred
+ }
+ BOOST_SCOPED_ENUM_DECLARE_END(future_status)
- class BOOST_SYMBOL_VISIBLE future_error
- : public std::logic_error
- {
- system::error_code ec_;
- public:
- future_error(system::error_code ec)
- : logic_error(ec.message()),
- ec_(ec)
- {
- }
+ class BOOST_SYMBOL_VISIBLE future_error
+ : public std::logic_error
+ {
+ system::error_code ec_;
+ public:
+ future_error(system::error_code ec)
+ : logic_error(ec.message()),
+ ec_(ec)
+ {
+ }
- const system::error_code& code() const BOOST_NOEXCEPT
- {
- return ec_;
- }
- };
+ const system::error_code& code() const BOOST_NOEXCEPT
+ {
+ return ec_;
+ }
+ };
class BOOST_SYMBOL_VISIBLE future_uninitialized:
public future_error
@@ -145,23 +145,23 @@
{}
};
- class BOOST_SYMBOL_VISIBLE task_moved:
- public future_error
- {
- public:
- task_moved():
- future_error(system::make_error_code(future_errc::no_state))
- {}
- };
+ class BOOST_SYMBOL_VISIBLE task_moved:
+ public future_error
+ {
+ public:
+ task_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
- class promise_moved:
- public future_error
- {
- public:
- promise_moved():
- future_error(system::make_error_code(future_errc::no_state))
- {}
- };
+ class promise_moved:
+ public future_error
+ {
+ public:
+ promise_moved():
+ future_error(system::make_error_code(future_errc::no_state))
+ {}
+ };
namespace future_state
{
@@ -171,20 +171,10 @@
namespace detail
{
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
- struct future_continuation_base
- {
- future_continuation_base() {}
- virtual ~future_continuation_base() {}
-
- virtual void do_continuation(boost::unique_lock<boost::mutex>& ) {};
- private:
- future_continuation_base(future_continuation_base const&);
- future_continuation_base& operator=(future_continuation_base const&);
- };
-
- template <typename F, typename R, typename C>
- struct future_continuation;
-
+ template<typename F, typename Rp, typename Fp>
+ struct future_deferred_continuation;
+ template<typename F, typename Rp, typename Fp>
+ struct future_async_continuation;
#endif
struct relocker
@@ -231,18 +221,29 @@
bool thread_was_interrupted;
//#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
- shared_ptr<future_continuation_base> continuation_ptr;
+ typedef shared_ptr<future_object_base> continuation_ptr_type;
#else
- shared_ptr<void> continuation_ptr;
+ typedef shared_ptr<void> continuation_ptr_type;
#endif
+ continuation_ptr_type continuation_ptr;
+
+
+//#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
+ {
+ }
+//#endif
future_object_base():
done(false),
is_deferred_(false),
policy_(launch::none),
is_constructed(false)
+
+ // This declaration should be only included conditinally, but are included to maintain the same layout.
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
, thread_was_interrupted(false)
//#endif
+ // This declaration should be only included conditinally, but are included to maintain the same layout.
//#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
, continuation_ptr()
//#endif
@@ -282,7 +283,10 @@
void do_continuation(boost::unique_lock<boost::mutex>& lock)
{
if (continuation_ptr) {
- continuation_ptr->do_continuation(lock);
+ continuation_ptr->launch_continuation(lock);
+ if (! lock.owns_lock())
+ lock.lock();
+ continuation_ptr.reset();
}
}
#else
@@ -291,9 +295,9 @@
}
#endif
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
- void set_continuation_ptr(future_continuation_base* continuation, boost::unique_lock<boost::mutex>& lock)
+ void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
{
- continuation_ptr.reset(continuation);
+ continuation_ptr= continuation;
if (done) {
do_continuation(lock);
}
@@ -330,7 +334,7 @@
void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
{
do_callback(lock);
- //if (!done) // fixme why this doesn't works?
+ //if (!done) // fixme why this doesn't work?
{
if (is_deferred_)
{
@@ -476,7 +480,7 @@
);
}
bool is_deferred() const BOOST_NOEXCEPT {
- return is_deferred_ == true;
+ return is_deferred_;
}
launch launch_policy() const BOOST_NOEXCEPT
@@ -500,26 +504,27 @@
template<typename T>
struct future_traits
{
- typedef boost::scoped_ptr<T> storage_type;
- struct dummy;
+ typedef boost::scoped_ptr<T> storage_type;
+ struct dummy;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- typedef T const& source_reference_type;
- //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
- typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
- //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
- typedef T move_dest_type;
+ typedef T const& source_reference_type;
+ //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
+ //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
+ typedef T move_dest_type;
#elif defined BOOST_THREAD_USES_MOVE
- typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
- //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
- //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
- typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
- typedef T move_dest_type;
-#else
- typedef T& source_reference_type;
- typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
- typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
+ typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
+ //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
+ //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
+ typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
+ typedef T move_dest_type;
+#else
+ typedef T& source_reference_type;
+ typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
+ typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
#endif
+
typedef const T& shared_future_get_result_type;
static void init(storage_type& storage,source_reference_type t)
@@ -547,8 +552,8 @@
{
typedef T* storage_type;
typedef T& source_reference_type;
- struct rvalue_source_type
- {};
+ //struct rvalue_source_type
+ //{};
typedef T& move_dest_type;
typedef T& shared_future_get_result_type;
@@ -600,13 +605,12 @@
{}
~future_object()
- {
- }
+ {}
void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
{
future_traits<T>::init(result,result_);
- mark_finished_internal(lock);
+ this->mark_finished_internal(lock);
}
void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
@@ -616,38 +620,36 @@
#else
future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
#endif
- mark_finished_internal(lock);
+ this->mark_finished_internal(lock);
}
void mark_finished_with_result(source_reference_type result_)
{
boost::unique_lock<boost::mutex> lock(mutex);
- mark_finished_with_result_internal(result_, lock);
+ this->mark_finished_with_result_internal(result_, lock);
}
void mark_finished_with_result(rvalue_source_type result_)
{
boost::unique_lock<boost::mutex> lock(mutex);
+
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
mark_finished_with_result_internal(boost::forward<T>(result_), lock);
#else
mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
#endif
-
}
- move_dest_type get()
+ virtual move_dest_type get()
{
wait();
- //return static_cast<move_dest_type>(*result);
return boost::move(*result);
}
shared_future_get_result_type get_sh()
{
wait();
- //return static_cast<shared_future_get_result_type>(*result);
return *result;
}
@@ -666,6 +668,7 @@
}
+ //void set_value_at_thread_exit(const T & result_)
void set_value_at_thread_exit(source_reference_type result_)
{
unique_lock<boost::mutex> lk(this->mutex);
@@ -679,13 +682,13 @@
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
}
+ //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
void set_value_at_thread_exit(rvalue_source_type result_)
{
unique_lock<boost::mutex> lk(this->mutex);
if (this->has_value(lk))
throw_exception(promise_already_satisfied());
result.reset(new T(boost::move(result_)));
- //result.reset(new T(boost::forward<T>(result_)));
//future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
@@ -703,7 +706,7 @@
{
typedef typename future_traits<T&>::storage_type storage_type;
typedef typename future_traits<T&>::source_reference_type source_reference_type;
- typedef typename future_traits<T&>::rvalue_source_type rvalue_source_type;
+ //typedef typename future_traits<T&>::rvalue_source_type rvalue_source_type;
typedef typename future_traits<T&>::move_dest_type move_dest_type;
typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type;
@@ -885,10 +888,9 @@
this->wait_internal(lock);
//return static_cast<move_dest_type>(*(this->result));
- return boost::move<Rp>(*(this->result));
-
+ //return boost::move<Rp>(*(this->result));
+ return boost::move(*(this->result));
}
-
static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f)
{
try
@@ -912,12 +914,11 @@
struct future_async_object<void, Fp>: public future_object<void>
{
typedef future_object<void> base_type;
-
boost::thread thr_;
public:
explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) :
- thr_(&future_async_object::run, this, boost::forward<Fp>(f))
+ thr_(&future_async_object::run, this, boost::forward<Fp>(f))
{
this->set_async();
}
@@ -946,6 +947,57 @@
}
}
};
+
+ template<typename Rp, typename Fp>
+ struct future_async_object<Rp&, Fp>: future_object<Rp&>
+ {
+ typedef future_object<Rp&> base_type;
+ typedef typename base_type::move_dest_type move_dest_type;
+
+ boost::thread thr_;
+
+ public:
+ explicit future_async_object(BOOST_THREAD_FWD_REF(Fp) f) :
+ thr_(&future_async_object::run, this, boost::forward<Fp>(f))
+ {
+ this->set_async();
+ }
+
+ ~future_async_object()
+ {
+ if (thr_.joinable()) thr_.join();
+ }
+
+ move_dest_type get()
+ {
+ if (thr_.joinable()) thr_.join();
+ // fixme Is the lock needed during the whole scope?
+ //this->wait();
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ this->wait_internal(lock);
+
+ //return static_cast<move_dest_type>(*(this->result));
+ return boost::move(*(this->result));
+ }
+ static void run(future_async_object* that, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ try
+ {
+ that->mark_finished_with_result(f());
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ that->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
+
//////////////////////////
/// future_deferred_object
//////////////////////////
@@ -973,6 +1025,30 @@
}
}
};
+ template<typename Rp, typename Fp>
+ struct future_deferred_object<Rp&,Fp>: future_object<Rp&>
+ {
+ typedef future_object<Rp&> base_type;
+ Fp func_;
+
+ public:
+ explicit future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f)
+ : func_(boost::forward<Fp>(f))
+ {
+ this->set_deferred();
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
+ {
+ this->mark_finished_with_result_internal(func_(), lck);
+ }
+ catch (...)
+ {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
template<typename Fp>
struct future_deferred_object<void,Fp>: future_object<void>
@@ -1376,9 +1452,9 @@
} // detail
BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
-#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
namespace detail
{
+#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
template <class Rp, class Fp>
BOOST_THREAD_FUTURE<Rp>
make_future_async_object(BOOST_THREAD_FWD_REF(Fp) f);
@@ -1386,9 +1462,20 @@
template <class Rp, class Fp>
BOOST_THREAD_FUTURE<Rp>
make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f);
- }
#endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <class F, class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+#endif
+
+ }
+
template <typename R>
class BOOST_THREAD_FUTURE : public detail::basic_future<R>
{
@@ -1400,7 +1487,9 @@
friend class promise<R>;
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
template <typename, typename, typename>
- friend struct detail::future_continuation;
+ friend struct detail::future_async_continuation;
+ template <typename, typename, typename>
+ friend struct detail::future_deferred_continuation;
#endif
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
template <class> friend class packaged_task; // todo check if this works in windows
@@ -1417,6 +1506,16 @@
friend BOOST_THREAD_FUTURE<Rp>
detail::make_future_deferred_object(BOOST_THREAD_FWD_REF(Fp) f);
+#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_async_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+
+ template <class F, class Rp, class Fp>
+ friend BOOST_THREAD_FUTURE<Rp>
+ detail::make_future_deferred_continuation(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
+#endif
+
typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
BOOST_THREAD_FUTURE(future_ptr a_future):
@@ -1453,6 +1552,17 @@
static_cast<base_type*>(this)->swap(other);
}
+ // todo this function must be private and friendship provided to the internal users.
+ void set_async()
+ {
+ this->future_->set_async();
+ }
+ // todo this function must be private and friendship provided to the internal users.
+ void set_deferred()
+ {
+ this->future_->set_deferred();
+ }
+
// retrieving the value
move_dest_type get()
{
@@ -1464,6 +1574,7 @@
future_ptr fut_=this->future_;
this->future_.reset();
return fut_->get();
+
#else
return this->future_->get();
#endif
@@ -1475,18 +1586,18 @@
// template<typename F>
// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
-#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
- template<typename RF>
- inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
- template<typename RF>
- inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
-#endif
+//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+// template<typename RF>
+// inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
+// template<typename RF>
+// inline BOOST_THREAD_FUTURE<RF> then(launch policy, 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);
+ then(BOOST_THREAD_FWD_REF(F) func);
template<typename F>
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
- then(launch policy, BOOST_THREAD_RV_REF(F) func);
+ then(launch policy, BOOST_THREAD_FWD_REF(F) func);
#endif
};
@@ -1675,11 +1786,7 @@
boost::throw_exception(future_already_retrieved());
}
future_obtained=true;
- return
- //BOOST_THREAD_MAKE_RV_REF(
- BOOST_THREAD_FUTURE<R>(future_)
- //)
- ;
+ return BOOST_THREAD_FUTURE<R>(future_);
}
void set_value(typename detail::future_traits<R>::source_reference_type r)
@@ -1847,7 +1954,6 @@
}
future_obtained=true;
return BOOST_THREAD_FUTURE<R&>(future_);
- //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<R&>(future_));
}
void set_value(R& r)
@@ -1993,9 +2099,6 @@
}
future_obtained=true;
return BOOST_THREAD_FUTURE<void>(future_);
- //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
- //BOOST_THREAD_FUTURE<void> res;
- //return boost::move(res);
}
void set_value()
@@ -2111,7 +2214,6 @@
#endif
}
-
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
@@ -2227,8 +2329,7 @@
#else
this->mark_finished_with_result(f());
#endif
-
- }
+ }
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
catch(thread_interrupted& )
@@ -2332,7 +2433,6 @@
}
};
-
#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
@@ -2372,9 +2472,8 @@
{
try
{
- //this->set_value_at_thread_exit(f());
- R r((f()));
- this->set_value_at_thread_exit(boost::move(r));
+ R r((f()));
+ this->set_value_at_thread_exit(boost::move(r));
}
#endif
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
@@ -2402,7 +2501,6 @@
{
try
{
- //this->set_value_at_thread_exit(f());
R res((f()));
this->mark_finished_with_result(boost::move(res));
}
@@ -2500,7 +2598,6 @@
}
};
#endif
-
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
template<typename F, typename ...ArgTypes>
@@ -2945,7 +3042,6 @@
{
future_obtained=true;
return BOOST_THREAD_FUTURE<R>(task);
- //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<R>(task));
}
else
{
@@ -3084,6 +3180,7 @@
packaged_task_type pt( f );
BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
+ ret.set_async();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread( boost::move(pt), boost::forward<ArgTypes>(args)... ).detach();
#else
@@ -3096,13 +3193,21 @@
packaged_task_type pt( f );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ ret.set_deferred();
return ::boost::move(ret);
} else {
+ //BOOST_THREAD_LOG << "ERROR async "<< int(policy) << BOOST_THREAD_END_LOG;
BOOST_THREAD_FUTURE<R> ret;
return ::boost::move(ret);
}
}
+// template <class R>
+// BOOST_THREAD_FUTURE<R>
+// async(R(*f)())
+// {
+// return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
+// }
#endif
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
@@ -3155,6 +3260,7 @@
packaged_task_type pt( boost::forward<F>(f) );
BOOST_THREAD_FUTURE<R> ret = pt.get_future();
+ ret.set_async();
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
boost::thread( boost::move(pt), boost::forward<ArgTypes>(args)... ).detach(); // todo forward
#else
@@ -3183,56 +3289,57 @@
#endif
} else {
+ //BOOST_THREAD_LOG << "ERROR async "<< int(policy) << BOOST_THREAD_END_LOG;
BOOST_THREAD_FUTURE<R> ret;
return ::boost::move(ret);
}
}
- ////////////////////////////////
- // template <class F, class... ArgTypes>
- // future<R> async(F&&, ArgTypes&&...);
- ////////////////////////////////
+ ////////////////////////////////
+ // template <class F, class... ArgTypes>
+ // future<R> async(F&&, ArgTypes&&...);
+ ////////////////////////////////
-#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+ #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
-#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
- template <class R, class... ArgTypes>
- BOOST_THREAD_FUTURE<R>
- async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
- {
- return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
- }
-#else
- template <class R>
- BOOST_THREAD_FUTURE<R>
- async(R(*f)())
- {
- return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
- }
-#endif
-#endif
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class R, class... ArgTypes>
+ BOOST_THREAD_FUTURE<R>
+ async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
+ {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
+ }
+ #else
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(R(*f)())
+ {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
+ }
+ #endif
+ #endif
-#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
- template <class F, class ...ArgTypes>
- BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
- typename decay<ArgTypes>::type...
- )>::type>
- async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
- {
- return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
- }
-#else
- template <class F>
- BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
- async(BOOST_THREAD_RV_REF(F) f)
- {
- return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
- }
+ #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ template <class F, class ...ArgTypes>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type>
+ async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
+ {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
+ }
+ #else
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
+ async(BOOST_THREAD_RV_REF(F) f)
+ {
+ return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
+ }
#endif
////////////////////////////////
- // make_future
+ // make_future deprecated
////////////////////////////////
template <typename T>
BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
@@ -3300,6 +3407,7 @@
return BOOST_THREAD_MAKE_RV_REF(p.get_future());
}
#endif
+
////////////////////////////////
// make_shared_future deprecated
////////////////////////////////
@@ -3350,116 +3458,352 @@
p.set_exception(ex);
return p.get_future().share();
}
+
////////////////////////////////
- // detail::future_continuation
+ // detail::future_async_continuation
////////////////////////////////
#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
namespace detail
{
- template <typename F, typename R, typename C>
- struct future_continuation : future_continuation_base
+
+ /////////////////////////
+ /// future_async_continuation
+ /////////////////////////
+
+ template<typename F, typename Rp, typename Fp>
+ struct future_async_continuation: future_object<Rp>
+ {
+ typedef future_object<Rp> base_type;
+ typedef typename base_type::move_dest_type move_dest_type;
+ typedef weak_ptr<future_object_base> parent_ptr_type;
+
+ F parent;
+ Fp continuation;
+ boost::thread thr_;
+
+ public:
+ explicit future_async_continuation(
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
+ ) :
+ parent(f.future_),
+ //continuation(boost::move(c)),
+ continuation(c),
+ thr_()
+ {
+ this->set_async();
+ }
+
+ ~future_async_continuation()
+ {
+ if (thr_.get_id()==thread::id())
+ {
+ //BOOST_THREAD_LOG << "ERRORRRRRRRRR ~future_async_continuation " << this << " " << thr_.get_id() << BOOST_THREAD_END_LOG;
+ return;
+ }
+ if (thr_.joinable()) {
+ thr_.join();
+ }
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& lock)
+ {
+ lock.unlock();
+ thr_ = thread(&future_async_continuation::run, this);
+ }
+
+ move_dest_type get()
+ {
+ if (thr_.joinable()) thr_.join();
+ // fixme Is the lock needed during the whole scope?
+ //this->wait();
+ boost::unique_lock<boost::mutex> lock(this->mutex);
+ this->wait_internal(lock);
+
+ // fixme use boost::move
+ return static_cast<move_dest_type>(*(this->result));
+ }
+ static void run(future_async_continuation* 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<typename F, typename Fp>
+ struct future_async_continuation<F, void, Fp>: public future_object<void>
+ {
+ typedef future_object<void> base_type;
+ F& parent;
+ Fp continuation;
+ boost::thread thr_;
+
+ public:
+ explicit future_async_continuation(
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
+ ) :
+ parent(f),
+ continuation(boost::move(c)),
+ thr_()
+ {
+ this->set_async();
+ }
+
+ ~future_async_continuation()
+ {
+ if (thr_.get_id()==thread::id())
+ {
+ return;
+ }
+ if (thr_.joinable()) thr_.join();
+ }
+
+ void launch_continuation(boost::unique_lock<boost::mutex>& lk)
{
- F& parent;
- C continuation;
- launch policy_;
- promise<R> next;
+ lk.unlock();
+ thr_ = thread(&future_async_continuation::run, this);
+ }
- future_continuation(F& f, BOOST_THREAD_FWD_REF(C) c) :
+ static void run(future_async_continuation* that)
+ {
+ try
+ {
+ that->continuation(that->parent);
+ that->mark_finished_with_result();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ that->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
+
+
+ //////////////////////////
+ /// future_deferred_continuation
+ //////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ struct future_deferred_continuation: future_object<Rp>
+ {
+ typedef future_object<Rp> base_type;
+ F& parent;
+ Fp continuation;
+
+ public:
+ explicit future_deferred_continuation(
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
+ ) :
parent(f),
- continuation(boost::forward<C>(c)),
- policy_(f.launch_policy()),
- next()
- {}
- future_continuation(F& f, BOOST_THREAD_FWD_REF(C) c, launch policy) :
+ //continuation(boost::move(c))
+ continuation(c)
+ {
+ this->set_deferred();
+ }
+
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
+ {
+ execute(lk);
+ }
+
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
+ {
+ this->mark_finished_with_result_internal(continuation(parent), lck);
+ }
+ catch (...)
+ {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ template<typename F, typename Fp>
+ struct future_deferred_continuation<F,void,Fp>: future_object<void>
+ {
+ typedef future_object<void> base_type;
+ F& parent;
+ Fp continuation;
+
+ public:
+ explicit future_deferred_continuation(
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
+ ):
parent(f),
- continuation(boost::forward<C>(c)),
- policy_(policy),
- next()
- {}
- ~future_continuation()
- {}
+ continuation(boost::move(c))
+ {
+ this->set_deferred();
+ }
- void do_continuation(boost::unique_lock<boost::mutex>& lk)
+ virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
+ {
+ execute(lk);
+ }
+ virtual void execute(boost::unique_lock<boost::mutex>& lck) {
+ try
{
- try
- {
- lk.unlock();
- // fixme what to do depending on inherits_launch_policy_ and policy_?
+ continuation(parent);
+ this->mark_finished_with_result_internal(lck);
+ }
+ catch (...)
+ {
+ this->mark_exceptional_finish_internal(current_exception(), lck);
+ }
+ }
+ };
+
+ ////////////////////////////////
+ // make_future_deferred_continuation
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_deferred_continuation(
+ boost::unique_lock<boost::mutex> &lock,
+ F& f, BOOST_THREAD_FWD_REF(Fp) c
+ )
+ {
+ shared_ptr<future_deferred_continuation<F, Rp, Fp> >
+ h(new future_deferred_continuation<F, Rp, Fp>(f, boost::forward<Fp>(c)));
+ f.future_->set_continuation_ptr(h, lock);
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+ ////////////////////////////////
+ // make_future_async_continuation
+ ////////////////////////////////
+ template<typename F, typename Rp, typename Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_async_continuation(
+ boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c
+ )
+ {
+ shared_ptr<future_async_continuation<F,Rp, Fp> >
+ h(new future_async_continuation<F,Rp, Fp>(f, boost::forward<Fp>(c)));
+ f.future_->set_continuation_ptr(h, lock);
+
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+// template <typename F, typename R, typename C>
+// struct future_continuation : future_object<R>
+// {
+// F& parent;
+// C continuation;
+// launch policy_;
+//
+// future_continuation(boost::unique_lock<boost::mutex>& lk, F& f, BOOST_THREAD_FWD_REF(C) c) :
+// parent(f),
+// continuation(boost::forward<C>(c)),
+// policy_(f.launch_policy())
+// {
+// init_continuation(lk);
+// }
+// future_continuation(boost::unique_lock<boost::mutex>& lk, F& f, BOOST_THREAD_FWD_REF(C) c, launch policy) :
+// parent(f),
+// continuation(boost::forward<C>(c)),
+// policy_(policy)
+// {
+// init_continuation(lk);
+// }
+// ~future_continuation()
+// {}
+//
+// void init_continuation(boost::unique_lock<boost::mutex>& lk)
+// {
+// try
+// {
+// lk.unlock();
+// // fixme what to do depending on inherits_launch_policy_ and policy_?
// if (int(policy_) & int(launch::deferred))
- {
- R val = continuation(parent);
- next.set_value(boost::move(val));
- }
+// {
+// R val = continuation(parent);
+// next.set_value(boost::move(val));
+// }
// else
// {
// BOOST_THREAD_FUTURE<R> f = async(policy_, continuation, boost::ref(parent));
// R val = f.get();
// 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&);
- };
-#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
- template <typename F, typename R, typename CR>
- struct future_continuation<F,R,CR(*)(F&)> : future_continuation_base
- {
- F& parent;
- CR(*continuation)(F&) ;
- launch policy_;
- promise<R> next;
-
- future_continuation(F& f, CR(*c)(F&)) :
- parent(f),
- continuation(c),
- policy_(f.launch_policy()),
- next()
- {}
- future_continuation(F& f, CR(*c)(F&), launch policy) :
- parent(f),
- continuation(c),
- policy_(policy),
- next()
- {}
- ~future_continuation()
- {}
-
- void do_continuation(boost::unique_lock<boost::mutex>& lk)
- {
- try
- {
- lk.unlock();
- // fixme what to do depending on inherits_launch_policy_ and policy_?
+// }
+// catch (...)
+// {
+// next.set_exception(boost::current_exception());
+// }
+// }
+// private:
+//
+// future_continuation(future_continuation const&);
+// future_continuation& operator=(future_continuation const&);
+// };
+//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+// template <typename F, typename R, typename CR>
+// struct future_continuation<F,R,CR(*)(F&)> : future_object<R>
+// {
+// F& parent;
+// CR(*continuation)(F&) ;
+// launch policy_;
+//
+// future_continuation(F& f, CR(*c)(F&)) :
+// parent(f),
+// continuation(c),
+// policy_(f.launch_policy()),
+// next()
+// {}
+// future_continuation(F& f, CR(*c)(F&), launch policy) :
+// parent(f),
+// continuation(c),
+// policy_(policy),
+// next()
+// {}
+// ~future_continuation()
+// {}
+//
+// void start_continuation(boost::unique_lock<boost::mutex>& lk)
+// {
+// try
+// {
+// lk.unlock();
+// // fixme what to do depending on inherits_launch_policy_ and policy_?
// if (int(policy_) & int(launch::deferred))
- {
- R val = continuation(parent);
- next.set_value(boost::move(val));
- }
+// {
+// R val = continuation(parent);
+// next.set_value(boost::move(val));
+// }
// else
// {
// BOOST_THREAD_FUTURE<R> f = async(policy_, continuation, boost::ref(parent));
// R val = f.get();
// 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
+// }
+// catch (...)
+// {
+// next.set_exception(boost::current_exception());
+// }
+// }
+// private:
+//
+// future_continuation(future_continuation const&);
+// future_continuation& operator=(future_continuation const&);
+// };
+//#endif
}
////////////////////////////////
@@ -3470,119 +3814,125 @@
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(launch policy, BOOST_THREAD_RV_REF(F) func)
+ BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
{
- typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
+ typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
- if (this->future_)
- {
- boost::unique_lock<boost::mutex> lock(this->future_->mutex);
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F > *ptr =
- new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(*this, boost::forward<F>(func), policy);
- if (ptr==0)
+ if (this->future_==0)
{
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+ // fixme what to do when the future has no associated state?
+ return BOOST_THREAD_FUTURE<future_type>();
}
- this->future_->set_continuation_ptr(ptr, lock);
- return BOOST_THREAD_MAKE_RV_REF(ptr->next.get_future());
- }
- else
+
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (int(policy) & int(launch::async))
{
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_FUTURE<future_type>();
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ )));
}
+ else
+ if (int(policy) & int(launch::deferred))
+ {
+ return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ )));
+ }
+ else
+ {
+ // fixme what to do when the policy is invalid?
+ return BOOST_THREAD_FUTURE<future_type>();
+ }
}
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(BOOST_THREAD_RV_REF(F) func)
+ BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
{
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
- if (this->future_)
+ if (this->future_==0)
{
- boost::unique_lock<boost::mutex> lock(this->future_->mutex);
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F > *ptr =
- new
- //BOOST_THREAD_MAKE_RV_REF((
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(*this, boost::forward<F>(func))
- //))
- ;
- if (ptr==0)
- {
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
- }
- this->future_->set_continuation_ptr(ptr, lock);
- return ptr->next.get_future();
- } else {
+ //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_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+ return BOOST_THREAD_FUTURE<future_type>();
}
- }
-#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
- 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 (this->future_)
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ if (int(this->launch_policy()) & int(launch::async))
{
- boost::unique_lock<boost::mutex> lock(this->future_->mutex);
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
- new
- //BOOST_THREAD_MAKE_RV_REF((
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func)
- // ))
- ;
- if (ptr==0)
- {
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
- }
- this->future_->set_continuation_ptr(ptr, lock);
- return ptr->next.get_future();
- } else {
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+ return boost::detail::make_future_async_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ );
+ }
+ else if (int(this->launch_policy()) & int(launch::deferred))
+ {
+ this->future_->wait_internal(lock);
+ return boost::detail::make_future_deferred_continuation<BOOST_THREAD_FUTURE<R>, future_type, F>(
+ lock, *this, boost::forward<F>(func)
+ );
}
-
- }
- template <typename R>
- template<typename RF>
- BOOST_THREAD_FUTURE<RF>
- BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
- {
-
- typedef RF future_type;
-
- if (this->future_)
+ else
{
- boost::unique_lock<boost::mutex> lock(this->future_->mutex);
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
- new
- //BOOST_THREAD_MAKE_RV_REF((
- detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy)
- // ))
- ;
- if (ptr==0)
- {
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
- }
- this->future_->set_continuation_ptr(ptr, lock);
- return ptr->next.get_future();
- } else {
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+ // fixme what to do when the policy is invalid?
+ return BOOST_THREAD_FUTURE<future_type>();
}
-
}
-#endif
+//#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
+// 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 (this->future_)
+// {
+// boost::unique_lock<boost::mutex> lock(this->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_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+// }
+// this->future_->set_continuation_ptr(ptr, lock);
+// return ptr->get_future();
+// } else {
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+// }
+//
+// }
+// template <typename R>
+// template<typename RF>
+// BOOST_THREAD_FUTURE<RF>
+// BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
+// {
+//
+// typedef RF future_type;
+//
+// if (this->future_)
+// {
+// boost::unique_lock<boost::mutex> lock(this->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, policy);
+// if (ptr==0)
+// {
+// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+// }
+// this->future_->set_continuation_ptr(ptr, lock);
+// return ptr->get_future();
+// } else {
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
+// }
+//
+// }
+//#endif
#endif
Modified: branches/release/libs/thread/example/future_then.cpp
==============================================================================
--- branches/release/libs/thread/example/future_then.cpp (original)
+++ branches/release/libs/thread/example/future_then.cpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -1,12 +1,11 @@
-// Copyright (C) 2012 Vicente Botet
+// Copyright (C) 2012-2013 Vicente Botet
//
// 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)
-//#define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
-#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
#include <boost/thread/detail/log.hpp>
#include <boost/thread/future.hpp>
@@ -46,11 +45,8 @@
try
{
boost::future<int> f1 = boost::async(boost::launch::async, &p1);
- BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
boost::future<int> f2 = f1.then(&p2);
- BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
- int i = f2.get();
- BOOST_THREAD_LOG << i << BOOST_THREAD_END_LOG;
+ (void)f2.get();
}
catch (std::exception& ex)
{
Modified: branches/release/libs/thread/example/tennis.cpp
==============================================================================
--- branches/release/libs/thread/example/tennis.cpp (original)
+++ branches/release/libs/thread/example/tennis.cpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -39,11 +39,10 @@
return 0;
}
-void player(void* param)
+void player(int active)
{
boost::unique_lock<boost::mutex> lock(mutex);
- int active = (int)param;
int other = active == PLAYER_A ? PLAYER_B : PLAYER_A;
while (state < GAME_OVER)
@@ -100,8 +99,8 @@
{
state = START;
- boost::thread thrda(thread_adapter(&player, (void*)PLAYER_A));
- boost::thread thrdb(thread_adapter(&player, (void*)PLAYER_B));
+ boost::thread thrda(&player, PLAYER_A);
+ boost::thread thrdb(&player, PLAYER_B);
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
@@ -112,7 +111,7 @@
std::cout << "---Noise ON..." << std::endl;
}
- for (int i = 0; i < 1000000000; ++i)
+ for (int i = 0; i < 10; ++i)
cond.notify_all();
{
Modified: branches/release/libs/thread/test/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/test/Jamfile.v2 (original)
+++ branches/release/libs/thread/test/Jamfile.v2 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -184,6 +184,15 @@
;
}
+rule thread-compile ( sources : reqs * : name )
+{
+ return
+ [ compile $(sources)
+ : $(reqs)
+ : $(name) ]
+ ;
+}
+
{
test-suite t_threads
:
@@ -334,7 +343,10 @@
[ thread-run2-noit ./sync/futures/future/move_ctor_pass.cpp : future__move_ctor_p ]
[ thread-run2-noit ./sync/futures/future/move_assign_pass.cpp : future__move_asign_p ]
[ thread-run2-noit ./sync/futures/future/share_pass.cpp : future__share_p ]
- #[ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ]
+ [ thread-run2-noit ./sync/futures/future/wait_pass.cpp : future__wait_p ]
+ [ thread-run2-noit ./sync/futures/future/wait_for_pass.cpp : future__wait_for_p ]
+ [ thread-run2-noit ./sync/futures/future/wait_until_pass.cpp : future__wait_until_p ]
+ [ thread-run2-noit ./sync/futures/future/then_pass.cpp : future__then_p ]
;
#explicit ts_shared_future ;
@@ -347,6 +359,9 @@
[ thread-run2-noit ./sync/futures/shared_future/get_pass.cpp : shared_future__get_p ]
[ thread-run2-noit ./sync/futures/shared_future/move_ctor_pass.cpp : shared_future__move_ctor_p ]
[ thread-run2-noit ./sync/futures/shared_future/move_assign_pass.cpp : shared_future__move_asign_p ]
+ [ thread-run2-noit ./sync/futures/shared_future/wait_pass.cpp : shared_future__wait_p ]
+ [ thread-run2-noit ./sync/futures/shared_future/wait_for_pass.cpp : shared_future__wait_for_p ]
+ [ thread-run2-noit ./sync/futures/shared_future/wait_until_pass.cpp : shared_future__wait_until_p ]
;
#explicit ts_packaged_task ;
@@ -615,6 +630,7 @@
[ thread-run2-noit ./threads/thread/assign/move_pass.cpp : thread__assign__move_p ]
[ thread-compile-fail ./threads/thread/constr/copy_fail.cpp : : thread__constr__copy_f ]
[ thread-run2-noit ./threads/thread/constr/default_pass.cpp : thread__constr__default_p ]
+ [ thread-run-lib2 ./threads/thread/constr/lambda_pass.cpp : thread__constr__lambda_p ]
[ thread-run-lib2 ./threads/thread/constr/F_pass.cpp : thread__constr__F_p ]
[ thread-run-lib2 ./threads/thread/constr/FArgs_pass.cpp : thread__constr__FArgs_p ]
[ thread-run2-noit ./threads/thread/constr/Frvalue_pass.cpp : thread__constr__Frvalue_p ]
@@ -645,31 +661,32 @@
test-suite ts_examples
:
[ thread-run2-noit ../example/monitor.cpp : ex_monitor ]
- [ compile ../example/starvephil.cpp ]
- #[ compile ../example/tennis.cpp ]
- [ compile ../example/condition.cpp ]
+ [ thread-compile ../example/starvephil.cpp : : ex_starvephil ]
+ [ thread-run2 ../example/tennis.cpp : ex_tennis ]
+ [ thread-compile ../example/condition.cpp : : ex_condition ]
[ thread-run2-noit ../example/mutex.cpp : ex_mutex ]
[ thread-run2-noit ../example/once.cpp : ex_once ]
[ thread-run2-noit ../example/recursive_mutex.cpp : ex_recursive_mutex ]
[ thread-run2-noit ../example/thread.cpp : ex_thread ]
[ thread-run2-noit ../example/thread_group.cpp : ex_thread_group ]
[ thread-run2-noit ../example/tss.cpp : ex_tss ]
- [ thread-run ../example/xtime.cpp ]
- [ thread-run ../example/shared_monitor.cpp ]
- [ thread-run ../example/shared_mutex.cpp ]
+ [ thread-run2 ../example/xtime.cpp : ex_xtime ]
+ [ thread-run2 ../example/shared_monitor.cpp : ex_shared_monitor ]
+ [ thread-run2 ../example/shared_mutex.cpp : ex_shared_mutex ]
#[ thread-run ../example/vhh_shared_monitor.cpp ]
#[ thread-run ../example/vhh_shared_mutex.cpp ]
- [ thread-run ../example/make_future.cpp ]
- #[ thread-run ../example/future_then.cpp ]
+ [ thread-run2 ../example/make_future.cpp : ex_make_future ]
+ [ thread-run2 ../example/future_then.cpp : ex_future_then ]
#[ thread-run2-noit ../example/synchronized_value.cpp : ex_synchronized_value ]
#[ thread-run2-noit ../example/synchronized_person.cpp : ex_synchronized_person ]
[ thread-run2-noit ../example/thread_guard.cpp : ex_thread_guard ]
[ thread-run2-noit ../example/scoped_thread.cpp : ex_scoped_thread ]
[ thread-run2-noit ../example/strict_lock.cpp : ex_strict_lock ]
[ thread-run2-noit ../example/ba_externallly_locked.cpp : ex_ba_externallly_locked ]
- [ thread-run ../example/producer_consumer_bounded.cpp ]
- [ thread-run ../example/producer_consumer.cpp ]
- [ thread-run ../example/not_interleaved.cpp ]
+ [ thread-run2 ../example/producer_consumer_bounded.cpp : ex_producer_consumer_bounded ]
+ [ thread-run2 ../example/producer_consumer.cpp : ex_producer_consumer ]
+ [ thread-run2 ../example/not_interleaved.cpp : ex_not_interleaved ]
+ [ thread-run2 ../example/lambda_future.cpp : ex_lambda_future ]
;
@@ -739,6 +756,7 @@
#[ thread-run ../example/unwrap.cpp ]
#[ thread-run ../example/perf_condition_variable.cpp ]
#[ thread-run ../example/perf_shared_mutex.cpp ]
+ #[ thread-run ../example/std_async_test.cpp ]
;
}
Modified: branches/release/libs/thread/test/sync/futures/async/async_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/async/async_pass.cpp (original)
+++ branches/release/libs/thread/test/sync/futures/async/async_pass.cpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -197,12 +197,12 @@
{
try {
boost::future<int> f = boost::async(boost::launch::async, BOOST_THREAD_MAKE_RV_REF(MoveOnly()));
- boost::this_thread::sleep_for(ms(300));
- Clock::time_point t0 = Clock::now();
- BOOST_TEST(f.get() == 3);
- Clock::time_point t1 = Clock::now();
- BOOST_TEST(t1 - t0 < ms(200));
- std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
+// boost::this_thread::sleep_for(ms(300));
+// Clock::time_point t0 = Clock::now();
+// BOOST_TEST(f.get() == 3);
+// Clock::time_point t1 = Clock::now();
+// BOOST_TEST(t1 - t0 < ms(200));
+// std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
} catch (std::exception& ex) {
std::cout << __FILE__ <<"["<<__LINE__<<"]"<<ex.what() << std::endl;
BOOST_TEST(false && "exception thrown");
Modified: branches/release/libs/thread/test/sync/futures/future/get_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/future/get_pass.cpp (original)
+++ branches/release/libs/thread/test/sync/futures/future/get_pass.cpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -93,20 +93,20 @@
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
typedef int T;
-// {
-// boost::promise<T> p;
-// boost::future<T> f = p.get_future();
-//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
-// boost::thread(func1, boost::move(p)).detach();
-//#else
-// p.set_value(3);
-//#endif
-// BOOST_TEST(f.valid());
-// BOOST_TEST(f.get() == 3);
-//#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
-// BOOST_TEST(!f.valid());
-//#endif
-// }
+ {
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func1, boost::move(p)).detach();
+#else
+ p.set_value(3);
+#endif
+ BOOST_TEST(f.valid());
+ BOOST_TEST(f.get() == 3);
+#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
+ BOOST_TEST(!f.valid());
+#endif
+ }
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
boost::promise<T> p;
Modified: branches/release/libs/thread/test/sync/futures/future/then_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/future/then_pass.cpp (original)
+++ branches/release/libs/thread/test/sync/futures/future/then_pass.cpp 2013-04-08 13:23:02 EDT (Mon, 08 Apr 2013)
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 Vicente J. Botet Escriba
+// Copyright (C) 2012-2013 Vicente Botet
//
// 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)
@@ -11,7 +11,6 @@
// auto then(F&& func) -> future<decltype(func(*this))>;
#define BOOST_THREAD_VERSION 4
-#define BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET
#define BOOST_THREAD_USES_LOG
#define BOOST_THREAD_USES_LOG_THREAD_ID
#include <boost/thread/detail/log.hpp>
@@ -23,61 +22,68 @@
int p1()
{
+ BOOST_THREAD_LOG << "p1 < " << BOOST_THREAD_END_LOG;
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ BOOST_THREAD_LOG << "p1 >" << BOOST_THREAD_END_LOG;
return 1;
}
int p2(boost::future<int>& f)
{
- return 2 * f.get();
+ BOOST_THREAD_LOG << "p2 <" << &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 << "p2 <" << &f << BOOST_THREAD_END_LOG;
+ return 2 * i;
}
int main()
{
+ {
+ 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);
+ BOOST_TEST(f2.valid());
+ try
+ {
+ BOOST_TEST(f2.get()==2);
+ }
+ 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> f1 = boost::async(boost::launch::async, p1);
- BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
- boost::future<int> f2 = f1.then(p2);
- BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
- try
{
+ boost::future<int> f2 = boost::async(p1).then(&p2);
BOOST_TEST(f2.get()==2);
- BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
}
- catch (std::exception& ex)
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
- BOOST_THREAD_LOG << "ERRORRRRR "<<ex.what() << "" << BOOST_THREAD_END_LOG;
- BOOST_ASSERT(false);
+ boost::future<int> f1 = boost::async(p1);
+ boost::future<int> f21 = f1.then(&p2);
+ boost::future<int> f2= f21.then(&p2);
+ BOOST_TEST(f2.get()==4);
}
- catch (...)
+ BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
{
- BOOST_THREAD_LOG << " ERRORRRRR exception thrown" << BOOST_THREAD_END_LOG;
- BOOST_ASSERT(false);
+ boost::future<int> f1 = boost::async(p1);
+ boost::future<int> f2= f1.then(&p2).then(&p2);
+ BOOST_TEST(f2.get()==4);
}
BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-
-// {
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// boost::future<int> f2 = boost::async(p1).then(p2);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// BOOST_TEST(f2.get()==2);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// }
-// {
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// boost::future<int> f1 = boost::async(p1);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// boost::future<int> f2 = f1.then(p2).then(p2);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// BOOST_TEST(f2.get()==4);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// }
-// {
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// boost::future<int> f2 = boost::async(p1).then(p2).then(p2);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// BOOST_TEST(f2.get()==4);
-// BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
-// }
+ {
+ boost::future<int> f2 = boost::async(p1).then(&p2).then(&p2);
+ BOOST_TEST(f2.get()==4);
+ }
return boost::report_errors();
}
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