321 lines
7.9 KiB
C++
321 lines
7.9 KiB
C++
#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
|
#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (C) Copyright Vicente J. Botet Escriba 2014-2015. 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)
|
|
//
|
|
// See http://www.boost.org/libs/thread for documentation.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <exception>
|
|
#include <boost/throw_exception.hpp>
|
|
#include <boost/thread/detail/config.hpp>
|
|
|
|
#include <boost/thread/future.hpp>
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
#include <boost/thread/executors/basic_thread_pool.hpp>
|
|
#endif
|
|
#include <boost/thread/experimental/exception_list.hpp>
|
|
#include <boost/thread/experimental/parallel/v2/inline_namespace.hpp>
|
|
#include <boost/thread/csbl/vector.hpp>
|
|
#include <boost/thread/detail/move.hpp>
|
|
|
|
#include <boost/config/abi_prefix.hpp>
|
|
|
|
#define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
|
|
namespace boost
|
|
{
|
|
namespace experimental
|
|
{
|
|
namespace parallel
|
|
{
|
|
BOOST_THREAD_INLINE_NAMESPACE(v2)
|
|
{
|
|
class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception
|
|
{
|
|
public:
|
|
//task_canceled_exception() BOOST_NOEXCEPT {}
|
|
//task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
|
//task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {}
|
|
virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW
|
|
{ return "task_canceled_exception";}
|
|
};
|
|
|
|
template <class Executor>
|
|
class task_region_handle_gen;
|
|
|
|
namespace detail
|
|
{
|
|
void handle_task_region_exceptions(exception_list& errors)
|
|
{
|
|
try {
|
|
throw;
|
|
}
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
catch (task_canceled_exception&)
|
|
{
|
|
}
|
|
#endif
|
|
catch (exception_list const& el)
|
|
{
|
|
for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it)
|
|
{
|
|
boost::exception_ptr const& e = *it;
|
|
try {
|
|
rethrow_exception(e);
|
|
}
|
|
catch (...)
|
|
{
|
|
handle_task_region_exceptions(errors);
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
errors.add(boost::current_exception());
|
|
}
|
|
}
|
|
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
template <class TRH, class F>
|
|
struct wrapped
|
|
{
|
|
TRH& tr;
|
|
F f;
|
|
wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f))
|
|
{}
|
|
void operator()()
|
|
{
|
|
try
|
|
{
|
|
f();
|
|
}
|
|
catch (...)
|
|
{
|
|
lock_guard<mutex> lk(tr.mtx);
|
|
tr.canceled = true;
|
|
throw;
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
}
|
|
|
|
template <class Executor>
|
|
class task_region_handle_gen
|
|
{
|
|
private:
|
|
// Private members and friends
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
template <class TRH, class F>
|
|
friend struct detail::wrapped;
|
|
#endif
|
|
template <typename F>
|
|
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
|
template<typename F>
|
|
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
|
template <class Ex, typename F>
|
|
friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
|
template<class Ex, typename F>
|
|
friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f);
|
|
|
|
void wait_all()
|
|
{
|
|
wait_for_all(group.begin(), group.end());
|
|
|
|
for (group_type::iterator it = group.begin(); it != group.end(); ++it)
|
|
{
|
|
BOOST_THREAD_FUTURE<void>& f = *it;
|
|
if (f.has_exception())
|
|
{
|
|
try
|
|
{
|
|
boost::rethrow_exception(f.get_exception_ptr());
|
|
}
|
|
catch (...)
|
|
{
|
|
detail::handle_task_region_exceptions(exs);
|
|
}
|
|
}
|
|
}
|
|
if (exs.size() != 0)
|
|
{
|
|
boost::throw_exception(exs);
|
|
}
|
|
}
|
|
protected:
|
|
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
task_region_handle_gen()
|
|
{}
|
|
#endif
|
|
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
task_region_handle_gen()
|
|
: canceled(false)
|
|
, ex(0)
|
|
{}
|
|
task_region_handle_gen(Executor& ex)
|
|
: canceled(false)
|
|
, ex(&ex)
|
|
{}
|
|
|
|
#endif
|
|
|
|
#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
task_region_handle_gen()
|
|
: ex(0)
|
|
{}
|
|
task_region_handle_gen(Executor& ex)
|
|
: ex(&ex)
|
|
{}
|
|
#endif
|
|
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
task_region_handle_gen()
|
|
: canceled(false)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
~task_region_handle_gen()
|
|
{
|
|
//wait_all();
|
|
}
|
|
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
mutable mutex mtx;
|
|
bool canceled;
|
|
#endif
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
Executor* ex;
|
|
#endif
|
|
exception_list exs;
|
|
typedef csbl::vector<BOOST_THREAD_FUTURE<void> > group_type;
|
|
group_type group;
|
|
|
|
public:
|
|
BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&))
|
|
BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&))
|
|
BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const)
|
|
|
|
public:
|
|
template<typename F>
|
|
void run(BOOST_THREAD_FWD_REF(F) f)
|
|
{
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
{
|
|
lock_guard<mutex> lk(mtx);
|
|
if (canceled) {
|
|
boost::throw_exception(task_canceled_exception());
|
|
}
|
|
}
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
group.push_back(async(*ex, detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
|
#else
|
|
group.push_back(async(detail::wrapped<task_region_handle_gen<Executor>, F>(*this, forward<F>(f))));
|
|
#endif
|
|
#else
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
group.push_back(async(*ex, forward<F>(f)));
|
|
#else
|
|
group.push_back(async(forward<F>(f)));
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void wait()
|
|
{
|
|
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
|
|
{
|
|
lock_guard<mutex> lk(mtx);
|
|
if (canceled) {
|
|
boost::throw_exception(task_canceled_exception());
|
|
}
|
|
}
|
|
#endif
|
|
wait_all();
|
|
}
|
|
};
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
typedef basic_thread_pool default_executor;
|
|
#else
|
|
typedef int default_executor;
|
|
#endif
|
|
class task_region_handle :
|
|
public task_region_handle_gen<default_executor>
|
|
{
|
|
default_executor tp;
|
|
template <typename F>
|
|
friend void task_region(BOOST_THREAD_FWD_REF(F) f);
|
|
template<typename F>
|
|
friend void task_region_final(BOOST_THREAD_FWD_REF(F) f);
|
|
|
|
protected:
|
|
task_region_handle() : task_region_handle_gen<default_executor>()
|
|
{
|
|
#if defined BOOST_THREAD_PROVIDES_EXECUTORS
|
|
ex = &tp;
|
|
#endif
|
|
}
|
|
BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&))
|
|
BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&))
|
|
BOOST_DELETED_FUNCTION(task_region_handle* operator&() const)
|
|
|
|
};
|
|
|
|
template <typename Executor, typename F>
|
|
void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
|
{
|
|
task_region_handle_gen<Executor> tr(ex);
|
|
try
|
|
{
|
|
f(tr);
|
|
}
|
|
catch (...)
|
|
{
|
|
detail::handle_task_region_exceptions(tr.exs);
|
|
}
|
|
tr.wait_all();
|
|
}
|
|
|
|
template <typename Executor, typename F>
|
|
void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f)
|
|
{
|
|
task_region_final(ex, forward<F>(f));
|
|
}
|
|
|
|
template <typename F>
|
|
void task_region_final(BOOST_THREAD_FWD_REF(F) f)
|
|
{
|
|
task_region_handle tr;
|
|
try
|
|
{
|
|
f(tr);
|
|
}
|
|
catch (...)
|
|
{
|
|
detail::handle_task_region_exceptions(tr.exs);
|
|
}
|
|
tr.wait_all();
|
|
}
|
|
|
|
template <typename F>
|
|
void task_region(BOOST_THREAD_FWD_REF(F) f)
|
|
{
|
|
task_region_final(forward<F>(f));
|
|
}
|
|
|
|
} // v2
|
|
} // parallel
|
|
} // experimental
|
|
} // boost
|
|
|
|
#include <boost/config/abi_suffix.hpp>
|
|
|
|
#endif // header
|