Chris@102: #ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP Chris@102: #define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP Chris@102: Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: // Chris@102: // (C) Copyright Vicente J. Botet Escriba 2014-2015. Distributed under the Boost Chris@102: // Software License, Version 1.0. (See accompanying file Chris@102: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // See http://www.boost.org/libs/thread for documentation. Chris@102: // Chris@102: ////////////////////////////////////////////////////////////////////////////// Chris@102: #include Chris@102: Chris@102: #include Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: #include Chris@102: #endif Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: Chris@102: #define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: Chris@102: namespace boost Chris@102: { Chris@102: namespace experimental Chris@102: { Chris@102: namespace parallel Chris@102: { Chris@102: BOOST_THREAD_INLINE_NAMESPACE(v2) Chris@102: { Chris@102: class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception Chris@102: { Chris@102: public: Chris@102: //task_canceled_exception() BOOST_NOEXCEPT {} Chris@102: //task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {} Chris@102: //task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {} Chris@102: virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW Chris@102: { return "task_canceled_exception";} Chris@102: }; Chris@102: Chris@102: template Chris@102: class task_region_handle_gen; Chris@102: Chris@102: namespace detail Chris@102: { Chris@102: void handle_task_region_exceptions(exception_list& errors) Chris@102: { Chris@102: try { Chris@102: throw; Chris@102: } Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: catch (task_canceled_exception& ex) Chris@102: { Chris@102: } Chris@102: #endif Chris@102: catch (exception_list const& el) Chris@102: { Chris@102: for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it) Chris@102: { Chris@102: boost::exception_ptr const& e = *it; Chris@102: try { Chris@102: rethrow_exception(e); Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: handle_task_region_exceptions(errors); Chris@102: } Chris@102: } Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: errors.add(boost::current_exception()); Chris@102: } Chris@102: } Chris@102: Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: template Chris@102: struct wrapped Chris@102: { Chris@102: TRH& tr; Chris@102: F f; Chris@102: wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f)) Chris@102: {} Chris@102: void operator()() Chris@102: { Chris@102: try Chris@102: { Chris@102: f(); Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: lock_guard lk(tr.mtx); Chris@102: tr.canceled = true; Chris@102: throw; Chris@102: } Chris@102: } Chris@102: }; Chris@102: #endif Chris@102: } Chris@102: Chris@102: template Chris@102: class task_region_handle_gen Chris@102: { Chris@102: private: Chris@102: // Private members and friends Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: template Chris@102: friend struct detail::wrapped; Chris@102: #endif Chris@102: template Chris@102: friend void task_region(BOOST_THREAD_FWD_REF(F) f); Chris@102: template Chris@102: friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); Chris@102: template Chris@102: friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f); Chris@102: template Chris@102: friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f); Chris@102: Chris@102: void wait_all() Chris@102: { Chris@102: wait_for_all(group.begin(), group.end()); Chris@102: Chris@102: for (group_type::iterator it = group.begin(); it != group.end(); ++it) Chris@102: { Chris@102: future& f = *it; Chris@102: if (f.has_exception()) Chris@102: { Chris@102: try Chris@102: { Chris@102: boost::rethrow_exception(f.get_exception_ptr()); Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: detail::handle_task_region_exceptions(exs); Chris@102: } Chris@102: } Chris@102: } Chris@102: if (exs.size() != 0) Chris@102: { Chris@102: boost::throw_exception(exs); Chris@102: } Chris@102: } Chris@102: protected: Chris@102: #if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: task_region_handle_gen() Chris@102: {} Chris@102: #endif Chris@102: Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: task_region_handle_gen() Chris@102: : canceled(false) Chris@102: , ex(0) Chris@102: {} Chris@102: task_region_handle_gen(Executor& ex) Chris@102: : canceled(false) Chris@102: , ex(&ex) Chris@102: {} Chris@102: Chris@102: #endif Chris@102: Chris@102: #if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: task_region_handle_gen() Chris@102: : ex(0) Chris@102: {} Chris@102: task_region_handle_gen(Executor& ex) Chris@102: : ex(&ex) Chris@102: {} Chris@102: #endif Chris@102: Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: task_region_handle_gen() Chris@102: : canceled(false) Chris@102: { Chris@102: } Chris@102: #endif Chris@102: Chris@102: ~task_region_handle_gen() Chris@102: { Chris@102: //wait_all(); Chris@102: } Chris@102: Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: mutable mutex mtx; Chris@102: bool canceled; Chris@102: #endif Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: Executor* ex; Chris@102: #endif Chris@102: exception_list exs; Chris@102: typedef csbl::vector > group_type; Chris@102: group_type group; Chris@102: Chris@102: public: Chris@102: BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&)) Chris@102: BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&)) Chris@102: BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const) Chris@102: Chris@102: public: Chris@102: template Chris@102: void run(BOOST_THREAD_FWD_REF(F) f) Chris@102: { Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: { Chris@102: lock_guard lk(mtx); Chris@102: if (canceled) { Chris@102: boost::throw_exception(task_canceled_exception()); Chris@102: } Chris@102: } Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: group.push_back(async(*ex, detail::wrapped, F>(*this, forward(f)))); Chris@102: #else Chris@102: group.push_back(async(detail::wrapped, F>(*this, forward(f)))); Chris@102: #endif Chris@102: #else Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: group.push_back(async(*ex, forward(f))); Chris@102: #else Chris@102: group.push_back(async(forward(f))); Chris@102: #endif Chris@102: #endif Chris@102: } Chris@102: Chris@102: void wait() Chris@102: { Chris@102: #if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED Chris@102: { Chris@102: lock_guard lk(mtx); Chris@102: if (canceled) { Chris@102: boost::throw_exception(task_canceled_exception()); Chris@102: } Chris@102: } Chris@102: #endif Chris@102: wait_all(); Chris@102: } Chris@102: }; Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: typedef basic_thread_pool default_executor; Chris@102: #else Chris@102: typedef int default_executor; Chris@102: #endif Chris@102: class task_region_handle : Chris@102: public task_region_handle_gen Chris@102: { Chris@102: default_executor tp; Chris@102: template Chris@102: friend void task_region(BOOST_THREAD_FWD_REF(F) f); Chris@102: template Chris@102: friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); Chris@102: Chris@102: protected: Chris@102: task_region_handle() : task_region_handle_gen() Chris@102: { Chris@102: #if defined BOOST_THREAD_PROVIDES_EXECUTORS Chris@102: ex = &tp; Chris@102: #endif Chris@102: } Chris@102: BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&)) Chris@102: BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&)) Chris@102: BOOST_DELETED_FUNCTION(task_region_handle* operator&() const) Chris@102: Chris@102: }; Chris@102: Chris@102: template Chris@102: void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f) Chris@102: { Chris@102: task_region_handle_gen tr(ex); Chris@102: try Chris@102: { Chris@102: f(tr); Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: detail::handle_task_region_exceptions(tr.exs); Chris@102: } Chris@102: tr.wait_all(); Chris@102: } Chris@102: Chris@102: template Chris@102: void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f) Chris@102: { Chris@102: task_region_final(ex, forward(f)); Chris@102: } Chris@102: Chris@102: template Chris@102: void task_region_final(BOOST_THREAD_FWD_REF(F) f) Chris@102: { Chris@102: task_region_handle tr; Chris@102: try Chris@102: { Chris@102: f(tr); Chris@102: } Chris@102: catch (...) Chris@102: { Chris@102: detail::handle_task_region_exceptions(tr.exs); Chris@102: } Chris@102: tr.wait_all(); Chris@102: } Chris@102: Chris@102: template Chris@102: void task_region(BOOST_THREAD_FWD_REF(F) f) Chris@102: { Chris@102: task_region_final(forward(f)); Chris@102: } Chris@102: Chris@102: } // v2 Chris@102: } // parallel Chris@102: } // experimental Chris@102: } // boost Chris@102: Chris@102: #include Chris@102: Chris@102: #endif // header