Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81205 - in trunk: boost/thread libs/thread/test libs/thread/test/sync/futures/packaged_task
From: vicente.botet_at_[hidden]
Date: 2012-11-05 12:41:10


Author: viboes
Date: 2012-11-05 12:41:09 EST (Mon, 05 Nov 2012)
New Revision: 81205
URL: http://svn.boost.org/trac/boost/changeset/81205

Log:
Thread: Added packaged_task::make_ready_at_thread_exit
Added:
   trunk/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp (contents, props changed)
Text files modified:
   trunk/boost/thread/future.hpp | 171 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/thread/test/Jamfile.v2 | 1
   2 files changed, 171 insertions(+), 1 deletions(-)

Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp (original)
+++ trunk/boost/thread/future.hpp 2012-11-05 12:41:09 EST (Mon, 05 Nov 2012)
@@ -448,6 +448,16 @@
                 thread_was_interrupted=true;
                 mark_finished_internal(lock);
             }
+ void set_interrupted_at_thread_exit()
+ {
+ unique_lock<boost::mutex> lk(mutex);
+ thread_was_interrupted=true;
+ if (has_value(lk))
+ {
+ throw_exception(promise_already_satisfied());
+ }
+ get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
+ }
 #endif
             void set_exception_at_thread_exit(exception_ptr e)
             {
@@ -672,7 +682,8 @@
               unique_lock<boost::mutex> lk(this->mutex);
               if (this->has_value(lk))
                   throw_exception(promise_already_satisfied());
- future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
+ result.reset(new T(boost::move(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());
             }
@@ -2079,6 +2090,29 @@
 #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)
+#else
+ virtual void do_apply()=0;
+ void apply()
+#endif
+ {
+ {
+ boost::lock_guard<boost::mutex> lk(this->mutex);
+ if(started)
+ {
+ boost::throw_exception(task_already_started());
+ }
+ started=true;
+ }
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ do_apply(boost::forward<ArgTypes>(args)...);
+#else
+ do_apply();
+#endif
+ }
+
             void owner_destroyed()
             {
                 boost::unique_lock<boost::mutex> lk(this->mutex);
@@ -2127,6 +2161,33 @@
 #endif
 
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f());
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
             void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
             {
                 try
@@ -2153,6 +2214,7 @@
                 }
             }
         };
+
 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
 
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
@@ -2178,6 +2240,36 @@
                 task_object(R (*f_)()):
                     f(f_)
                 {}
+
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
+ }
+#else
+ void do_apply()
+ {
+ try
+ {
+ this->set_value_at_thread_exit(f());
+ }
+#endif
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
                 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
                 {
@@ -2241,6 +2333,33 @@
 #endif
 
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::forward<ArgTypes>(args)...);
+#else
+ void do_apply()
+ {
+ try
+ {
+ f();
+#endif
+ this->set_value_at_thread_exit();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
             void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
             {
                 try
@@ -2291,6 +2410,34 @@
             task_object(void (*f_)()):
                 f(f_)
             {}
+
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
+ {
+ try
+ {
+ f(boost::forward<ArgTypes>(args)...);
+#else
+ void do_apply()
+ {
+ try
+ {
+ f();
+#endif
+ this->set_value_at_thread_exit();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ this->set_interrupted_at_thread_exit();
+ }
+#endif
+ catch(...)
+ {
+ this->set_exception_at_thread_exit(current_exception());
+ }
+ }
+
 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
             void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
             {
@@ -2612,6 +2759,18 @@
             }
             task->run(boost::forward<ArgTypes>(args)...);
         }
+ void make_ready_at_thread_exit(ArgTypes... args)
+ {
+ if(!task)
+ {
+ boost::throw_exception(task_moved());
+ }
+ if (task->has_value())
+ {
+ boost::throw_exception(promise_already_satisfied());
+ }
+ task->apply(boost::forward<ArgTypes>(args)...);
+ }
 #else
         void operator()()
         {
@@ -2621,6 +2780,16 @@
             }
             task->run();
         }
+ void make_ready_at_thread_exit()
+ {
+ if(!task)
+ {
+ boost::throw_exception(task_moved());
+ }
+ if (task->has_value())
+ boost::throw_exception(promise_already_satisfied());
+ task->apply();
+ }
 #endif
         template<typename F>
         void set_wait_callback(F f)

Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2 (original)
+++ trunk/libs/thread/test/Jamfile.v2 2012-11-05 12:41:09 EST (Mon, 05 Nov 2012)
@@ -587,6 +587,7 @@
     explicit ts_ ;
     test-suite ts_
     :
+ [ thread-run2 ./sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp : packaged_task__make_ready_at_thread_exit_p ]
 
           #[ thread-run ../example/unwrap.cpp ]
     ;

Added: trunk/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/sync/futures/packaged_task/make_ready_at_thread_exit_pass.cpp 2012-11-05 12:41:09 EST (Mon, 05 Nov 2012)
@@ -0,0 +1,146 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Copyright (C) 2011 Vicente J. Botet Escriba
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// <boost/thread/future.hpp>
+
+// class packaged_task<R>
+
+// packaged_task(packaged_task&& other);
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/future.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined BOOST_THREAD_USES_CHRONO && \
+ defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && \
+ defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+
+class E : public std::exception
+{
+public:
+ long data;
+ explicit E(long i) :
+ data(i)
+ {
+ }
+
+ const char* what() const throw() { return ""; }
+
+ ~E() throw() {}
+};
+class A
+{
+ long data_;
+
+public:
+ explicit A(long i) :
+ data_(i)
+ {
+ }
+
+ long operator()(long i, long j) const
+ {
+ if (j == 'z') BOOST_THROW_EXCEPTION( E(6) );
+ return data_ + i + j;
+ }
+};
+
+void func0(boost::packaged_task<double(int, char)> *p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p->make_ready_at_thread_exit(3, 'a');
+}
+
+void func1(boost::packaged_task<double(int, char)> *p)
+{
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
+ p->make_ready_at_thread_exit(3, 'z');
+}
+
+void func2(boost::packaged_task<double(int, char)> *p)
+{
+ p->make_ready_at_thread_exit(3, 'a');
+ try
+ {
+ p->make_ready_at_thread_exit(3, 'c');
+ }
+ catch (const boost::future_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::promise_already_satisfied));
+ }
+}
+
+void func3(boost::packaged_task<double(int, char)> *p)
+{
+ try
+ {
+ p->make_ready_at_thread_exit(3, 'a');
+ }
+ catch (const boost::future_error& e)
+ {
+ BOOST_TEST(e.code() == boost::system::make_error_code(boost::future_errc::no_state));
+ }
+}
+
+int main()
+{
+ {
+ boost::packaged_task<double(int, char)> p(A(5));
+ boost::future<double> f = p.get_future();
+ // BUG boost::thread(func0, boost::move(p)).detach();
+ boost::thread(func0, &p).detach();
+ BOOST_TEST(f.get() == 105.0);
+ }
+ {
+ boost::packaged_task<double(int, char)> p(A(5));
+ boost::future<double> f = p.get_future();
+ //boost::thread(func1, boost::move(p)).detach();
+ boost::thread(func1, &p).detach();
+ try
+ {
+ f.get();
+ BOOST_TEST(false);
+ }
+ catch (const E& e)
+ {
+ BOOST_TEST(e.data == 6);
+ }
+ }
+ {
+ boost::packaged_task<double(int, char)> p(A(5));
+ boost::future<double> f = p.get_future();
+ //boost::thread(func2, boost::move(p)).detach();
+ boost::thread(func2, &p).detach();
+ BOOST_TEST(f.get() == 105.0);
+ }
+ {
+ boost::packaged_task<double(int, char)> p;
+ //boost::thread t(func3, boost::move(p));
+ boost::thread t(func3, &p);
+ t.join();
+ }
+
+ return boost::report_errors();
+}
+
+#else
+int main()
+{
+ return boost::report_errors();
+}
+//#error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
+#endif
+
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk