|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r84678 - in trunk: boost/thread libs/thread/test/sync/futures/promise libs/thread/test/threads/thread/constr
From: vicente.botet_at_[hidden]
Date: 2013-06-07 15:03:49
Author: viboes
Date: 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013)
New Revision: 84678
URL: http://svn.boost.org/trac/boost/changeset/84678
Log:
Thread: fix promise set_at_..._thread_exit; Added preconditions.
Text files modified:
trunk/boost/thread/future.hpp | 148 +++++++++++++++++++++++++++++++--------
trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp | 19 ++++-
trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp | 25 +++++-
trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp | 4
trunk/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp | 51 +++++++++++++
5 files changed, 206 insertions(+), 41 deletions(-)
Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp Fri Jun 7 13:37:04 2013 (r84677)
+++ trunk/boost/thread/future.hpp 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013) (r84678)
@@ -429,6 +429,7 @@
throw_exception(promise_already_satisfied());
}
exception=e;
+ this->is_constructed = true;
get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
}
@@ -1399,7 +1400,11 @@
BOOST_THREAD_FUTURE<Rp>
make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, F& f, BOOST_THREAD_FWD_REF(Fp) c);
#endif
-
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ template <class F, class Rp>
+ typename BOOST_THREAD_FUTURE<Rp>::value_type
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_FUTURE<Rp>& f);
+#endif
}
template <typename R>
@@ -1525,6 +1530,15 @@
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE&)>::type>
then(launch policy, BOOST_THREAD_FWD_REF(F) func);
#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ inline
+ typename enable_if_c<
+ is_future<value_type>::value,
+ BOOST_THREAD_FUTURE<typename value_type::value_type>
+ >::type
+ unwrap();
+#endif
+
};
BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
@@ -1639,6 +1653,15 @@
inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future&)>::type>
then(launch policy, BOOST_THREAD_FWD_REF(F) func);
#endif
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ inline
+ typename enable_if_c<
+ is_future<value_type>::value,
+ BOOST_THREAD_FUTURE<typename value_type::value_type>
+ >::type
+ unwrap();
+#endif
+
};
BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
@@ -1703,7 +1726,7 @@
{
boost::unique_lock<boost::mutex> lock(future_->mutex);
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
{
future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
}
@@ -1785,7 +1808,11 @@
}
future_->mark_exceptional_finish_internal(p, lock);
}
-
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(copy_exception(ex));
+ }
// setting the result with deferred notification
void set_value_at_thread_exit(const R& r)
{
@@ -1812,6 +1839,11 @@
}
future_->set_exception_at_thread_exit(e);
}
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(copy_exception(ex));
+ }
template<typename F>
void set_wait_callback(F f)
@@ -1872,7 +1904,7 @@
{
boost::unique_lock<boost::mutex> lock(future_->mutex);
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
{
future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
}
@@ -1938,6 +1970,11 @@
}
future_->mark_exceptional_finish_internal(p, lock);
}
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(copy_exception(ex));
+ }
// setting the result with deferred notification
void set_value_at_thread_exit(R& r)
@@ -1957,6 +1994,11 @@
}
future_->set_exception_at_thread_exit(e);
}
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(copy_exception(ex));
+ }
template<typename F>
void set_wait_callback(F f)
@@ -2014,7 +2056,7 @@
{
boost::unique_lock<boost::mutex> lock(future_->mutex);
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
{
future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
}
@@ -2083,6 +2125,11 @@
}
future_->mark_exceptional_finish_internal(p,lock);
}
+ template <typename E>
+ void set_exception(E ex)
+ {
+ set_exception(copy_exception(ex));
+ }
// setting the result with deferred notification
void set_value_at_thread_exit()
@@ -2102,6 +2149,11 @@
}
future_->set_exception_at_thread_exit(e);
}
+ template <typename E>
+ void set_exception_at_thread_exit(E ex)
+ {
+ set_exception_at_thread_exit(copy_exception(ex));
+ }
template<typename F>
void set_wait_callback(F f)
@@ -3607,12 +3659,13 @@
{
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
- if (this->future_==0)
- {
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_FUTURE<future_type>();
- }
+// if (this->future_==0)
+// {
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_FUTURE<future_type>();
+// }
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(policy) & int(launch::async))
@@ -3630,7 +3683,8 @@
else
{
// fixme what to do when the policy is invalid?
- return BOOST_THREAD_FUTURE<future_type>();
+ BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
+ //return BOOST_THREAD_FUTURE<future_type>();
}
}
@@ -3641,13 +3695,14 @@
{
typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>&)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
- if (this->future_==0)
- {
- //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_FUTURE<future_type>();
- }
+// if (this->future_==0)
+// {
+// //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_FUTURE<future_type>();
+// }
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
@@ -3666,7 +3721,8 @@
else
{
// fixme what to do when the policy is invalid?
- return BOOST_THREAD_FUTURE<future_type>();
+ BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
+ //return BOOST_THREAD_FUTURE<future_type>();
}
}
@@ -3731,12 +3787,13 @@
{
typedef typename boost::result_of<F(shared_future<R>&)>::type future_type;
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
- if (this->future_==0)
- {
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_FUTURE<future_type>();
- }
+// if (this->future_==0)
+// {
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_FUTURE<future_type>();
+// }
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(policy) & int(launch::async))
@@ -3754,7 +3811,8 @@
else
{
// fixme what to do when the policy is invalid?
- return BOOST_THREAD_FUTURE<future_type>();
+ BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
+ //return BOOST_THREAD_FUTURE<future_type>();
}
}
@@ -3766,12 +3824,13 @@
typedef typename boost::result_of<F(shared_future<R>&)>::type future_type;
- if (this->future_==0)
- {
- //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
- // fixme what to do when the future has no associated state?
- return BOOST_THREAD_FUTURE<future_type>();
- }
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
+// if (this->future_==0)
+// {
+// //BOOST_THREAD_LOG << "ERROR future::then " << this << BOOST_THREAD_END_LOG;
+// // fixme what to do when the future has no associated state?
+// return BOOST_THREAD_FUTURE<future_type>();
+// }
boost::unique_lock<boost::mutex> lock(this->future_->mutex);
if (int(this->launch_policy()) & int(launch::async))
@@ -3790,11 +3849,36 @@
else
{
// fixme what to do when the policy is invalid?
- return BOOST_THREAD_FUTURE<future_type>();
+ BOOST_THREAD_ASSERT_PRECONDITION(false && "invalid launch parameter", std::logic_error("invalid launch parameter"));
+ //return BOOST_THREAD_FUTURE<future_type>();
}
}
#endif
-
+#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
+ namespace detail
+ {
+ template <class Rp>
+ typename BOOST_THREAD_FUTURE<Rp>::value_type
+ make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_FUTURE<Rp>& f)
+ {
+ shared_ptr<future_unwrap_shared_state<Rp> >
+ h(new future_unwrap_shared_state<Rp>(f, boost::forward<Fp>(c)));
+ f.future_->set_continuation_ptr(h, lock);
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+ }
+ template <typename R>
+ typename enable_if_c<
+ is_future<value_type>::value,
+ value_type>
+ >::type
+ future<R>::unwrap()
+ {
+ BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized())
+ boost::unique_lock<boost::mutex> lock(this->future_->mutex);
+ return boost::detail::make_future_unwrap_shared_state(lock, *this);
+ }
+#endif
}
#endif // BOOST_NO_EXCEPTION
Modified: trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp Fri Jun 7 13:37:04 2013 (r84677)
+++ trunk/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013) (r84678)
@@ -44,10 +44,14 @@
}
}
-//void func(boost::promise<int> p)
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+void func(boost::promise<int> p)
+#else
boost::promise<int> p;
void func()
+#endif
{
+ //p.set_exception(boost::make_exception_ptr(3));
p.set_exception_at_thread_exit(boost::make_exception_ptr(3));
}
@@ -55,10 +59,14 @@
{
{
typedef int T;
- //boost::promise<T> p;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ boost::thread(func, boost::move(p)).detach();
+#else
boost::future<T> f = p.get_future();
- //boost::thread(func, boost::move(p)).detach();
boost::thread(func).detach();
+#endif
try
{
f.get();
@@ -77,9 +85,12 @@
typedef int T;
boost::promise<T> p2;
boost::future<T> f = p2.get_future();
- //boost::thread(func, boost::move(p)).detach();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func, boost::move(p2)).detach();
+#else
p = boost::move(p2);
boost::thread(func).detach();
+#endif
try
{
f.get();
Modified: trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp Fri Jun 7 13:37:04 2013 (r84677)
+++ trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013) (r84678)
@@ -23,9 +23,12 @@
#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+void func(boost::promise<int> p)
+#else
boost::promise<int> p;
-//void func(boost::promise<int> p)
void func()
+#endif
{
const int i = 5;
p.set_value_at_thread_exit(i);
@@ -34,18 +37,32 @@
int main()
{
{
- //boost::promise<int> p;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::promise<int> p;
+ boost::future<int> f = p.get_future();
+ boost::thread(func, boost::move(p)).detach();
+#else
boost::future<int> f = p.get_future();
- //boost::thread(func, boost::move(p)).detach();
boost::thread(func).detach();
- BOOST_TEST(f.get() == 5);
+#endif
+ try
+ {
+ BOOST_TEST(f.get() == 5);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
}
{
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+#else
boost::promise<int> p2;
boost::future<int> f = p2.get_future();
p = boost::move(p2);
boost::thread(func).detach();
BOOST_TEST(f.get() == 5);
+#endif
}
return boost::report_errors();
}
Modified: trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp Fri Jun 7 13:37:04 2013 (r84677)
+++ trunk/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013) (r84678)
@@ -32,7 +32,8 @@
i = 1;
}
-void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2)
+//void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2)
+void func2_mv(boost::promise<void> p2)
{
p2.set_value_at_thread_exit();
i = 2;
@@ -92,6 +93,7 @@
boost::thread(func2, &p2).detach();
#endif
f.wait();
+ f.get();
BOOST_TEST(i == 2);
}
catch(std::exception& ex)
Modified: trunk/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp
==============================================================================
--- trunk/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp Fri Jun 7 13:37:04 2013 (r84677)
+++ trunk/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp 2013-06-07 15:03:49 EDT (Fri, 07 Jun 2013) (r84678)
@@ -40,6 +40,51 @@
}
};
+class M
+{
+
+public:
+ long data_;
+ static int n_moves;
+
+ BOOST_THREAD_MOVABLE_ONLY(M)
+ static void reset() {
+ n_moves=0;
+ }
+ explicit M(long i) : data_(i)
+ {
+ }
+ M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_)
+ {
+ BOOST_THREAD_RV(a).data_ = -1;
+ ++n_moves;
+ }
+ M& operator=(BOOST_THREAD_RV_REF(M) a)
+ {
+ data_ = BOOST_THREAD_RV(a).data_;
+ BOOST_THREAD_RV(a).data_ = -1;
+ ++n_moves;
+ return *this;
+ }
+ ~M()
+ {
+ }
+
+ void operator()(int) const
+ { }
+ long operator()() const
+ { return data_;}
+ long operator()(long i, long j) const
+ { return data_ + i + j;}
+};
+
+int M::n_moves = 0;
+
+void fct(BOOST_THREAD_RV_REF(M) v)
+{
+ BOOST_TEST_EQ(v.data_, 1);
+}
+
int main()
{
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
@@ -47,6 +92,12 @@
boost::thread t = boost::thread( MoveOnly(), MoveOnly() );
t.join();
}
+ {
+ M::reset();
+ boost::thread t = boost::thread( fct, M(1) );
+ t.join();
+ BOOST_TEST_EQ(M::n_moves, 2);
+ }
#endif
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