Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86327 - in trunk: boost/thread boost/thread/detail libs/thread/test/sync/futures/async
From: vicente.botet_at_[hidden]
Date: 2013-10-16 02:15:51


Author: viboes
Date: 2013-10-16 02:15:51 EDT (Wed, 16 Oct 2013)
New Revision: 86327
URL: http://svn.boost.org/trac/boost/changeset/86327

Log:
Thread: first steps toward async(executor&, f).

Text files modified:
   trunk/boost/thread/detail/move.hpp | 56 ++++++++
   trunk/boost/thread/executor.hpp | 3
   trunk/boost/thread/future.hpp | 257 +++++++++++++++++++++++++++++++++++++++
   trunk/libs/thread/test/sync/futures/async/async_pass.cpp | 97 ++++++++++++++
   4 files changed, 404 insertions(+), 9 deletions(-)

Modified: trunk/boost/thread/detail/move.hpp
==============================================================================
--- trunk/boost/thread/detail/move.hpp Tue Oct 15 12:49:34 2013 (r86326)
+++ trunk/boost/thread/detail/move.hpp 2013-10-16 02:15:51 EDT (Wed, 16 Oct 2013) (r86327)
@@ -14,13 +14,22 @@
 #include <boost/type_traits/remove_reference.hpp>
 #include <boost/type_traits/remove_cv.hpp>
 #include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/remove_extent.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/decay.hpp>
 #endif
 
 #include <boost/thread/detail/delete.hpp>
 #include <boost/move/utility.hpp>
 #include <boost/move/traits.hpp>
 #include <boost/config/abi_prefix.hpp>
-
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <type_traits>
+#endif
 namespace boost
 {
 
@@ -237,8 +246,51 @@
 
 
 namespace boost
-{ namespace thread_detail
+{
+ namespace thread_detail
+ {
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class Tp>
+ struct remove_reference : boost::remove_reference<Tp> {};
+ template <class Tp>
+ struct decay : boost::decay<Tp> {};
+#else
+ template <class Tp>
+ struct remove_reference
   {
+ typedef Tp type;
+ };
+ template <class Tp>
+ struct remove_reference<Tp&>
+ {
+ typedef Tp type;
+ };
+ template <class Tp>
+ struct remove_reference< rv<Tp> > {
+ typedef Tp type;
+ };
+
+ template <class Tp>
+ struct decay
+ {
+ private:
+ typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0;
+ typedef typename boost::remove_reference<Up0>::type Up;
+ public:
+ typedef typename conditional
+ <
+ is_array<Up>::value,
+ typename remove_extent<Up>::type*,
+ typename conditional
+ <
+ is_function<Up>::value,
+ typename add_pointer<Up>::type,
+ typename remove_cv<Up>::type
+ >::type
+ >::type type;
+ };
+#endif
+
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
       template <class T>
       typename decay<T>::type

Modified: trunk/boost/thread/executor.hpp
==============================================================================
--- trunk/boost/thread/executor.hpp Tue Oct 15 12:49:34 2013 (r86326)
+++ trunk/boost/thread/executor.hpp 2013-10-16 02:15:51 EDT (Wed, 16 Oct 2013) (r86327)
@@ -135,6 +135,9 @@
 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
     template <typename ...Args>
     executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
+#else
+ template <typename A1>
+ executor_adaptor(BOOST_THREAD_FWD_REF(A1) a1) : ex(boost::forward<A1>(a1)) {}
 #endif
     /**
      * \b Effects: close the \c executor for submissions.

Modified: trunk/boost/thread/future.hpp
==============================================================================
--- trunk/boost/thread/future.hpp Tue Oct 15 12:49:34 2013 (r86326)
+++ trunk/boost/thread/future.hpp 2013-10-16 02:15:51 EDT (Wed, 16 Oct 2013) (r86327)
@@ -71,6 +71,10 @@
 //#define BOOST_THREAD_VECTOR std::vector
 #endif
 
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+#include <boost/thread/executor.hpp>
+#endif
+
 #if defined BOOST_THREAD_PROVIDES_FUTURE
 #define BOOST_THREAD_FUTURE future
 #else
@@ -86,6 +90,9 @@
       none = 0,
       async = 1,
       deferred = 2,
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ executor = 4,
+#endif
       any = async | deferred
   }
   BOOST_SCOPED_ENUM_DECLARE_END(launch)
@@ -256,7 +263,13 @@
               is_deferred_ = false;
               policy_ = launch::async;
             }
-
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ void set_executor()
+ {
+ is_deferred_ = false;
+ policy_ = launch::executor;
+ }
+#endif
             waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
             {
                 boost::unique_lock<boost::mutex> lock(mutex);
@@ -3565,6 +3578,248 @@
         }
     }
 
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ namespace detail {
+ /////////////////////////
+ /// shared_state_nullary_task
+ /////////////////////////
+ template<typename Rp, typename Fp>
+ struct shared_state_nullary_task
+ {
+ shared_state<Rp>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::forward<Fp>(f))
+ {};
+ void operator()()
+ {
+ 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();
+ }
+
+ }
+ };
+
+ template<typename Fp>
+ struct shared_state_nullary_task<void, Fp>
+ {
+ shared_state<void>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::forward<Fp>(f))
+ {};
+ void operator()()
+ {
+ try
+ {
+ f_();
+ that->mark_finished_with_result();
+ }
+#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
+ catch(thread_interrupted& )
+ {
+ that->mark_interrupted_finish();
+ }
+#endif
+ catch(...)
+ {
+ that->mark_exceptional_finish();
+ }
+ }
+ };
+
+ template<typename Rp, typename Fp>
+ struct shared_state_nullary_task<Rp&, Fp>
+ {
+ shared_state<Rp&>* that;
+ Fp f_;
+ public:
+ shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f)
+ : that(st), f_(boost::forward<Fp>(f))
+ {};
+ void operator()()
+ {
+ 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_executor_shared_state_base
+ /////////////////////////
+ template<typename Rp>
+ struct future_executor_shared_state: shared_state<Rp>
+ {
+ typedef shared_state<Rp> base_type;
+ protected:
+ boost::executor& ex_;
+ public:
+ template<typename Fp>
+ future_executor_shared_state(boost::executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
+ : ex_(ex)
+ {
+ this->set_executor();
+ shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f));
+ ex_.submit(boost::move(t));
+ }
+
+ ~future_executor_shared_state()
+ {
+ this->wait(false);
+ }
+ };
+
+ ////////////////////////////////
+ // make_future_executor_shared_state
+ ////////////////////////////////
+ template <class Rp, class Fp>
+ BOOST_THREAD_FUTURE<Rp>
+ make_future_executor_shared_state(executor& ex, BOOST_THREAD_FWD_REF(Fp) f)
+ {
+ shared_ptr<future_executor_shared_state<Rp> >
+ h(new future_executor_shared_state<Rp>(ex, boost::forward<Fp>(f)));
+ return BOOST_THREAD_FUTURE<Rp>(h);
+ }
+
+ } // detail
+
+ ////////////////////////////////
+ // template <class F, class... ArgTypes>
+ // future<R> async(executor& ex, F&&, ArgTypes&&...);
+ ////////////////////////////////
+
+ #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class R, class... ArgTypes>
+ BOOST_THREAD_FUTURE<R>
+ async(executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
+ {
+ 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;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ }
+ #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class F, class ...ArgTypes>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<ArgTypes>::type...
+ )>::type>
+ async(executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
+ {
+ typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
+ )
+ ));
+ }
+ #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+
+ template <class R>
+ BOOST_THREAD_FUTURE<R>
+ async(executor& ex, R(*f)())
+ {
+ typedef R(*F)();
+ typedef detail::async_func<typename decay<F>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ )
+ ));
+ }
+
+ template <class R, class A1>
+ BOOST_THREAD_FUTURE<R>
+ async(executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1)
+ {
+ typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
+ typedef detail::async_func<typename decay<F>::type, typename decay<A1>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<A1>(a1))
+ )
+ ));
+ }
+
+ #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
+ template <class F>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
+ async(executor& ex, BOOST_THREAD_FWD_REF(F) f)
+ {
+ typedef detail::async_func<typename decay<F>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ )
+ );
+ }
+
+ template <class F, class A1>
+ BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
+ typename decay<A1>::type
+ )>::type>
+ async(executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1)
+ {
+ typedef detail::async_func<typename decay<F>::type, typename decay<A1>::type> BF;
+ typedef typename BF::result_type Rp;
+
+ return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
+ BF(
+ thread_detail::decay_copy(boost::forward<F>(f))
+ , thread_detail::decay_copy(boost::forward<A1>(a1))
+ )
+ ));
+ }
+
+ #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+
+#endif
+
         ////////////////////////////////
         // template <class F, class... ArgTypes>
         // future<R> async(F&&, ArgTypes&&...);

Modified: trunk/libs/thread/test/sync/futures/async/async_pass.cpp
==============================================================================
--- trunk/libs/thread/test/sync/futures/async/async_pass.cpp Tue Oct 15 12:49:34 2013 (r86326)
+++ trunk/libs/thread/test/sync/futures/async/async_pass.cpp 2013-10-16 02:15:51 EDT (Wed, 16 Oct 2013) (r86327)
@@ -22,8 +22,13 @@
 // future<typename result_of<F(Args...)>::type>
 // async(launch policy, F&& f, Args&&... args);
 
+// template <class F, class... Args>
+// future<typename result_of<F(Args...)>::type>
+// async(executor& ex, F&& f, Args&&... args);
+
 //#define BOOST_THREAD_VERSION 3
 #define BOOST_THREAD_VERSION 4
+#define BOOST_THREAD_PROVIDES_EXECUTORS
 
 #include <iostream>
 #include <boost/thread/future.hpp>
@@ -32,6 +37,9 @@
 #include <boost/interprocess/smart_ptr/unique_ptr.hpp>
 #include <memory>
 #include <boost/detail/lightweight_test.hpp>
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+#include <boost/thread/thread_pool.hpp>
+#endif
 
 typedef boost::chrono::high_resolution_clock Clock;
 typedef boost::chrono::milliseconds ms;
@@ -210,6 +218,30 @@
     }
 
   }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
+ {
+ try
+ {
+ boost::executor_adaptor<boost::thread_pool> ex(1);
+ boost::future<int> f = boost::async(ex, &f0);
+ 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(300));
+ 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");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+ }
+#endif
   std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
   {
     try
@@ -233,17 +265,43 @@
     }
 
   }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS2
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ try
+ {
+ boost::executor_adaptor<boost::thread_pool> ex(1);
+ boost::future<long> f = boost::async(ex, A(3));
+ 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(300));
+ 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");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+
+ }
+#endif
   std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
   {
     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(300));
- // 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(300));
+ std::cout << __FILE__ <<"["<<__LINE__<<"] "<< (t1 - t0).count() << std::endl;
     }
     catch (std::exception& ex)
     {
@@ -255,6 +313,33 @@
       BOOST_TEST(false && "exception thrown");
     }
   }
+#ifdef BOOST_THREAD_PROVIDES_EXECUTORS2
+ std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
+ {
+ try
+ {
+ boost::executor_adaptor<boost::thread_pool> ex(1);
+ MoveOnly mo;
+ boost::future<int> f = boost::async(ex, boost::move(mo));
+ //boost::future<int> f = boost::async(ex, 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(300));
+ 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");
+ }
+ catch (...)
+ {
+ BOOST_TEST(false && "exception thrown");
+ }
+ }
+#endif
   std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
   {
     try


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