$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r84468 - in branches/release: boost/thread boost/thread/detail libs/thread libs/thread/test/sync/futures/packaged_task
From: vicente.botet_at_[hidden]
Date: 2013-05-24 17:27:54
Author: viboes
Date: 2013-05-24 17:27:53 EDT (Fri, 24 May 2013)
New Revision: 84468
URL: http://svn.boost.org/trac/boost/changeset/84468
Log:
Thread: merge 84414 to fix #8596.
Properties modified: 
   branches/release/boost/thread/   (props changed)
   branches/release/libs/thread/   (props changed)
Text files modified: 
   branches/release/boost/thread/detail/config.hpp                                 |     6                                         
   branches/release/boost/thread/future.hpp                                        |    77 ++++++++----------                      
   branches/release/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp |   161 +++++++++++++++++++++++++++++++++++++-- 
   3 files changed, 187 insertions(+), 57 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-05-24 17:27:53 EDT (Fri, 24 May 2013)
@@ -13,8 +13,6 @@
 #include <boost/thread/detail/platform.hpp>
 
 //#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
-
-
 // ATTRIBUTE_MAY_ALIAS
 
 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
@@ -95,9 +93,9 @@
 #endif
 
 /// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
-#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
+//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC
 #define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
-#endif
+//#endif
 
 // Default version
 #if !defined BOOST_THREAD_VERSION
Modified: branches/release/boost/thread/future.hpp
==============================================================================
--- branches/release/boost/thread/future.hpp	(original)
+++ branches/release/boost/thread/future.hpp	2013-05-24 17:27:53 EDT (Fri, 24 May 2013)
@@ -2275,18 +2275,12 @@
           task_object(task_object&);
         public:
             F f;
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-            task_object(BOOST_THREAD_RV_REF(F) f_):
-              f(boost::forward<F>(f_))
-            {}
-#else
             task_object(F const& f_):
                 f(f_)
             {}
             task_object(BOOST_THREAD_RV_REF(F) f_):
-                f(boost::move(f_)) // TODO forward
+              f(boost::move(f_))
             {}
-#endif
 
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
             void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
@@ -2837,12 +2831,11 @@
 #endif
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
         template <class F>
-        explicit packaged_task(BOOST_THREAD_RV_REF(F) f
+        explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
             , typename disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
             )
         {
-          //typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
-          typedef F FR;
+          typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
   #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
             typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
@@ -2921,10 +2914,9 @@
 
 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
         template <class F, class Allocator>
-        packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
+        packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
         {
-          //typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
-          typedef F FR;
+          typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
   #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
           typedef detail::task_object<FR,R(ArgTypes...)> task_object_type;
@@ -3150,11 +3142,6 @@
     // future<R> async(launch policy, 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_PROVIDES_SIGNATURE_PACKAGED_TASK
@@ -3163,8 +3150,9 @@
         BOOST_THREAD_FUTURE<R>
         async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
         {
-          //typedef packaged_task<R(BOOST_THREAD_FWD_REF(ArgTypes)...)> packaged_task_type;
-          typedef packaged_task<R(ArgTypes...)> packaged_task_type;
+          typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
+          typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+          typedef typename BF::result_type Rp;
   #else
         template <class R>
         BOOST_THREAD_FUTURE<R>
@@ -3181,37 +3169,44 @@
 #endif
           if (int(policy) & int(launch::async))
             {
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+          return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_object<Rp>(
+              BF(
+                  thread_detail::decay_copy(boost::forward<F>(f))
+                  , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+              )
+          ));
+#else
               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
               boost::thread( boost::move(pt) ).detach();
-#endif
               return ::boost::move(ret);
+#endif
             }
             else if (int(policy) & int(launch::deferred))
             {
-              packaged_task_type pt( f );
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+          return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_object<Rp>(
+              BF(
+                  thread_detail::decay_copy(boost::forward<F>(f))
+                  , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+              )
+          ));
+#else
+          std::terminate();
+          BOOST_THREAD_FUTURE<R> ret;
+          return ::boost::move(ret);
 
-              BOOST_THREAD_FUTURE<R> ret = pt.get_future();
-              ret.set_deferred();
-              return ::boost::move(ret);
+#endif
             } else {
-              //BOOST_THREAD_LOG << "ERROR async "<< int(policy) << BOOST_THREAD_END_LOG;
+              std::terminate();
               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
@@ -3227,7 +3222,6 @@
           typedef typename boost::result_of<typename decay<F>::type(
               typename decay<ArgTypes>::type...
           )>::type R;
-          typedef packaged_task<R(ArgTypes...)> packaged_task_type;
 
           typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
           typedef typename BF::result_type Rp;
@@ -3265,11 +3259,11 @@
 
           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
+//#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
           boost::thread( boost::move(pt) ).detach();
-#endif
+//#endif
           return ::boost::move(ret);
 #endif
         }
@@ -3283,6 +3277,7 @@
               )
           ));
 #else
+              std::terminate();
               BOOST_THREAD_FUTURE<R> ret;
               return ::boost::move(ret);
 //          return boost::detail::make_future_deferred_object<Rp>(
@@ -3293,7 +3288,7 @@
 #endif
 
         } else {
-          //BOOST_THREAD_LOG << "ERROR async "<< int(policy) << BOOST_THREAD_END_LOG;
+          std::terminate();
           BOOST_THREAD_FUTURE<R> ret;
           return ::boost::move(ret);
         }
Modified: branches/release/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp	(original)
+++ branches/release/libs/thread/test/sync/futures/packaged_task/func_ctor_pass.cpp	2013-05-24 17:27:53 EDT (Fri, 24 May 2013)
@@ -54,24 +54,43 @@
 
 class A
 {
+public:
   long data_;
 
-public:
-  BOOST_THREAD_COPYABLE_AND_MOVABLE(A)
   static int n_moves;
   static int n_copies;
+  BOOST_THREAD_COPYABLE_AND_MOVABLE(A)
+  static void reset()
+  {
+    n_moves=0;
+    n_copies=0;
+  }
 
   explicit A(long i) : data_(i)
   {
   }
   A(BOOST_THREAD_RV_REF(A) a) : data_(BOOST_THREAD_RV(a).data_)
   {
-    ++n_moves; BOOST_THREAD_RV(a).data_ = -1;
+    BOOST_THREAD_RV(a).data_ = -1;
+    ++n_moves;
+  }
+  A& operator=(BOOST_THREAD_RV_REF(A) a)
+  {
+    data_ = BOOST_THREAD_RV(a).data_;
+    BOOST_THREAD_RV(a).data_ = -1;
+    ++n_moves;
+    return *this;
   }
   A(const A& a) : data_(a.data_)
   {
     ++n_copies;
   }
+  A& operator=(A const& a)
+  {
+    data_ = a.data_;
+    ++n_copies;
+    return *this;
+  }
   ~A()
   {
   }
@@ -85,6 +104,78 @@
 int A::n_moves = 0;
 int A::n_copies = 0;
 
+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()
+  {
+  }
+
+  long operator()() const
+  { return data_;}
+  long operator()(long i, long j) const
+  { return data_ + i + j;}
+};
+
+int M::n_moves = 0;
+
+class C
+{
+public:
+  long data_;
+
+  static int n_copies;
+  static void reset()
+  {
+    n_copies=0;
+  }
+
+  explicit C(long i) : data_(i)
+  {
+  }
+  C(const C& a) : data_(a.data_)
+  {
+    ++n_copies;
+  }
+  C& operator=(C const& a)
+  {
+    data_ = a.data_;
+    ++n_copies;
+    return *this;
+  }
+  ~C()
+  {
+  }
+
+  long operator()() const
+  { return data_;}
+  long operator()(long i, long j) const
+  { return data_ + i + j;}
+};
+int C::n_copies = 0;
 
 int main()
 {
@@ -99,11 +190,10 @@
 #endif
       BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES);
       BOOST_TEST(A::n_copies == 0);
-      BOOST_TEST(A::n_moves > 0);
+      BOOST_TEST_EQ(A::n_moves, 1);
   }
-  A::n_copies = 0;
-  A::n_moves = 0;
   {
+    A::reset();
       A a(5);
       boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a);
       BOOST_TEST(p.valid());
@@ -111,13 +201,12 @@
       //p(3, 'a');
       p();
       BOOST_TEST(f.get() == 5.0);
-      //BOOST_TEST(A::n_copies > 0);
-      //BOOST_TEST(A::n_moves > 0);
+      BOOST_TEST_EQ(A::n_copies, 1);
+      BOOST_TEST_EQ(A::n_moves, 0);
   }
 
-  A::n_copies = 0;
-  A::n_moves = 0;
   {
+    A::reset();
       const A a(5);
       boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a);
       BOOST_TEST(p.valid());
@@ -125,8 +214,56 @@
       //p(3, 'a');
       p();
       BOOST_TEST(f.get() == 5.0);
-      //BOOST_TEST(A::n_copies > 0);
-      //BOOST_TEST(A::n_moves > 0);
+      BOOST_TEST_EQ(A::n_copies, 1);
+      BOOST_TEST_EQ(A::n_moves, 0);
+  }
+  {
+    M::reset();
+      boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE_2> p(BOOST_THREAD_MAKE_RV_REF(M(5)));
+      BOOST_TEST(p.valid());
+      boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+      p(3, 'a');
+#else
+      p();
+#endif
+      BOOST_TEST(f.get() == BOOST_THREAD_DETAIL_SIGNATURE_2_RES);
+      BOOST_TEST_EQ(M::n_moves, 1);
+  }
+  {
+    M::reset();
+      M a(5);
+      boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(boost::move(a));
+      BOOST_TEST(p.valid());
+      boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
+      //p(3, 'a');
+      p();
+      BOOST_TEST(f.get() == 5.0);
+      BOOST_TEST_EQ(M::n_moves, 1);
+  }
+
+  {
+    C::reset();
+      C a(5);
+      boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a);
+      BOOST_TEST(p.valid());
+      boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
+      //p(3, 'a');
+      p();
+      BOOST_TEST(f.get() == 5.0);
+      BOOST_TEST_EQ(C::n_copies, 1);
+  }
+
+  {
+    C::reset();
+      const C a(5);
+      boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(a);
+      BOOST_TEST(p.valid());
+      boost::future<double> f = BOOST_THREAD_MAKE_RV_REF(p.get_future());
+      //p(3, 'a');
+      p();
+      BOOST_TEST(f.get() == 5.0);
+      BOOST_TEST_EQ(C::n_copies, 1);
   }
   {
       boost::packaged_task<BOOST_THREAD_DETAIL_SIGNATURE> p(fct);