Boost logo

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