Import Geant4 10.7.0 source tree
This commit is contained in:
+17
-17
@@ -255,15 +255,15 @@ namespace PTL
|
||||
// Note: Note that TemplateAutoLock by itself is not thread-safe and
|
||||
// cannot be shared among threads due to the locked switch
|
||||
//
|
||||
template <typename _Mutex_t>
|
||||
class TemplateAutoLock : public std::unique_lock<_Mutex_t>
|
||||
template <typename MutexT>
|
||||
class TemplateAutoLock : public std::unique_lock<MutexT>
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
// Some useful typedefs
|
||||
//------------------------------------------------------------------------//
|
||||
typedef std::unique_lock<_Mutex_t> unique_lock_t;
|
||||
typedef TemplateAutoLock<_Mutex_t> this_type;
|
||||
typedef std::unique_lock<MutexT> unique_lock_t;
|
||||
typedef TemplateAutoLock<MutexT> this_type;
|
||||
typedef typename unique_lock_t::mutex_type mutex_type;
|
||||
|
||||
public:
|
||||
@@ -350,26 +350,26 @@ public:
|
||||
|
||||
private:
|
||||
// helpful macros
|
||||
#define _is_stand_mutex(_Tp) (std::is_same<_Tp, Mutex>::value)
|
||||
#define _is_recur_mutex(_Tp) (std::is_same<_Tp, RecursiveMutex>::value)
|
||||
#define _is_other_mutex(_Tp) (!_is_stand_mutex(_Tp) && !_is_recur_mutex(_Tp))
|
||||
#define _is_stand_mutex(Tp) (std::is_same<Tp, Mutex>::value)
|
||||
#define _is_recur_mutex(Tp) (std::is_same<Tp, RecursiveMutex>::value)
|
||||
#define _is_other_mutex(Tp) (!_is_stand_mutex(Tp) && !_is_recur_mutex(Tp))
|
||||
|
||||
template <typename _Tp = _Mutex_t,
|
||||
typename std::enable_if<_is_stand_mutex(_Tp), int>::type = 0>
|
||||
template <typename Tp = MutexT,
|
||||
typename std::enable_if<_is_stand_mutex(Tp), int>::type = 0>
|
||||
std::string GetTypeString()
|
||||
{
|
||||
return "AutoLock<Mutex>";
|
||||
}
|
||||
|
||||
template <typename _Tp = _Mutex_t,
|
||||
typename std::enable_if<_is_recur_mutex(_Tp), int>::type = 0>
|
||||
template <typename Tp = MutexT,
|
||||
typename std::enable_if<_is_recur_mutex(Tp), int>::type = 0>
|
||||
std::string GetTypeString()
|
||||
{
|
||||
return "AutoLock<RecursiveMutex>";
|
||||
}
|
||||
|
||||
template <typename _Tp = _Mutex_t,
|
||||
typename std::enable_if<_is_other_mutex(_Tp), int>::type = 0>
|
||||
template <typename Tp = MutexT,
|
||||
typename std::enable_if<_is_other_mutex(Tp), int>::type = 0>
|
||||
std::string GetTypeString()
|
||||
{
|
||||
return "AutoLock<UNKNOWN_MUTEX>";
|
||||
@@ -381,8 +381,8 @@ private:
|
||||
#undef _is_other_mutex
|
||||
|
||||
// used in _lock_deferred chrono variants to avoid ununsed-variable warning
|
||||
template <typename _Tp>
|
||||
void suppress_unused_variable(const _Tp&)
|
||||
template <typename Tp>
|
||||
void suppress_unused_variable(const Tp&)
|
||||
{}
|
||||
|
||||
//========================================================================//
|
||||
@@ -485,7 +485,7 @@ typedef TemplateAutoLock<RecursiveMutex> RecursiveAutoLock;
|
||||
|
||||
// provide abbriviated type if another mutex type is desired to be used
|
||||
// aside from above
|
||||
template <typename _Tp>
|
||||
using TAutoLock = TemplateAutoLock<_Tp>;
|
||||
template <typename Tp>
|
||||
using TAutoLock = TemplateAutoLock<Tp>;
|
||||
|
||||
} // namespace PTL
|
||||
|
||||
+55
-57
@@ -42,7 +42,7 @@
|
||||
|
||||
#if !defined(PTL_FOLD_EXPRESSION)
|
||||
# define PTL_FOLD_EXPRESSION(...) \
|
||||
::PTL::details::consume_parameters( \
|
||||
::PTL::mpl::consume_parameters( \
|
||||
::std::initializer_list<int>{ (__VA_ARGS__, 0)... })
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ template <bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
// for pre-C++14 tuple expansion to arguments
|
||||
namespace details
|
||||
namespace mpl
|
||||
{
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
@@ -71,84 +71,83 @@ namespace impl
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// Stores a tuple of indices. Used by tuple and pair, and by bind() to
|
||||
// extract the elements in a tuple.
|
||||
template <size_t... _Indexes>
|
||||
struct _Index_tuple
|
||||
template <size_t... Indexes>
|
||||
struct Index_tuple
|
||||
{};
|
||||
|
||||
// Concatenates two _Index_tuples.
|
||||
template <typename _Itup1, typename _Itup2>
|
||||
struct _Itup_cat;
|
||||
// Concatenates two Index_tuples.
|
||||
template <typename Itup1, typename Itup2>
|
||||
struct Itup_cat;
|
||||
|
||||
template <size_t... _Ind1, size_t... _Ind2>
|
||||
struct _Itup_cat<_Index_tuple<_Ind1...>, _Index_tuple<_Ind2...>>
|
||||
template <size_t... Ind1, size_t... Ind2>
|
||||
struct Itup_cat<Index_tuple<Ind1...>, Index_tuple<Ind2...>>
|
||||
{
|
||||
using __type = _Index_tuple<_Ind1..., (_Ind2 + sizeof...(_Ind1))...>;
|
||||
using __type = Index_tuple<Ind1..., (Ind2 + sizeof...(Ind1))...>;
|
||||
};
|
||||
|
||||
// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
|
||||
template <size_t _Num>
|
||||
struct _Build_index_tuple
|
||||
: _Itup_cat<typename _Build_index_tuple<_Num / 2>::__type,
|
||||
typename _Build_index_tuple<_Num - _Num / 2>::__type>
|
||||
// Builds an Index_tuple<0, 1, 2, ..., NumT-1>.
|
||||
template <size_t NumT>
|
||||
struct Build_index_tuple
|
||||
: Itup_cat<typename Build_index_tuple<NumT / 2>::__type,
|
||||
typename Build_index_tuple<NumT - NumT / 2>::__type>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct _Build_index_tuple<1>
|
||||
struct Build_index_tuple<1>
|
||||
{
|
||||
typedef _Index_tuple<0> __type;
|
||||
typedef Index_tuple<0> __type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _Build_index_tuple<0>
|
||||
struct Build_index_tuple<0>
|
||||
{
|
||||
typedef _Index_tuple<> __type;
|
||||
typedef Index_tuple<> __type;
|
||||
};
|
||||
|
||||
/// Class template integer_sequence
|
||||
template <typename _Tp, _Tp... _Idx>
|
||||
template <typename Tp, Tp... Idx>
|
||||
struct integer_sequence
|
||||
{
|
||||
typedef _Tp value_type;
|
||||
static constexpr size_t size() noexcept { return sizeof...(_Idx); }
|
||||
typedef Tp value_type;
|
||||
static constexpr size_t size() noexcept { return sizeof...(Idx); }
|
||||
};
|
||||
|
||||
template <typename _Tp, _Tp _Num,
|
||||
typename _ISeq = typename _Build_index_tuple<_Num>::__type>
|
||||
struct _Make_integer_sequence;
|
||||
template <typename Tp, Tp NumT, typename ISeq = typename Build_index_tuple<NumT>::__type>
|
||||
struct Make_integer_sequence;
|
||||
|
||||
template <typename _Tp, _Tp _Num, size_t... _Idx>
|
||||
struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>>
|
||||
template <typename Tp, Tp NumT, size_t... Idx>
|
||||
struct Make_integer_sequence<Tp, NumT, Index_tuple<Idx...>>
|
||||
{
|
||||
static_assert(_Num >= 0, "Cannot make integer sequence of negative length");
|
||||
static_assert(NumT >= 0, "Cannot make integer sequence of negative length");
|
||||
|
||||
typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type;
|
||||
typedef integer_sequence<Tp, static_cast<Tp>(Idx)...> __type;
|
||||
};
|
||||
|
||||
/// Alias template make_integer_sequence
|
||||
template <typename _Tp, _Tp _Num>
|
||||
using make_integer_sequence = typename _Make_integer_sequence<_Tp, _Num>::__type;
|
||||
template <typename Tp, Tp NumT>
|
||||
using make_integer_sequence = typename Make_integer_sequence<Tp, NumT>::__type;
|
||||
|
||||
/// Alias template index_sequence
|
||||
template <size_t... _Idx>
|
||||
using index_sequence = integer_sequence<size_t, _Idx...>;
|
||||
template <size_t... Idx>
|
||||
using index_sequence = integer_sequence<size_t, Idx...>;
|
||||
|
||||
/// Alias template make_index_sequence
|
||||
template <size_t _Num>
|
||||
using make_index_sequence = make_integer_sequence<size_t, _Num>;
|
||||
template <size_t NumT>
|
||||
using make_index_sequence = make_integer_sequence<size_t, NumT>;
|
||||
|
||||
/// Alias template index_sequence_for
|
||||
template <typename... _Types>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
|
||||
template <typename... Types>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(Types)>;
|
||||
|
||||
template <size_t I, typename Tup>
|
||||
using index_type_t = decay_t<decltype(std::get<I>(std::declval<Tup>()))>;
|
||||
template <size_t Idx, typename Tup>
|
||||
using index_type_t = decay_t<decltype(std::get<Idx>(std::declval<Tup>()))>;
|
||||
|
||||
template <typename _Fn, typename _Tuple, size_t... _Idx>
|
||||
static inline void
|
||||
apply(_Fn&& __f, _Tuple&& __t, impl::index_sequence<_Idx...>)
|
||||
template <typename FnT, typename TupleT, size_t... Idx>
|
||||
static inline auto
|
||||
apply(FnT&& __f, TupleT&& __t, impl::index_sequence<Idx...>)
|
||||
-> decltype(std::forward<FnT>(__f)(std::get<Idx>(__t)...))
|
||||
{
|
||||
std::forward<_Fn>(__f)(std::get<_Idx>(std::forward<_Tuple>(__t))...);
|
||||
// __f(std::get<_Idx>(std::forward<_Tuple>(__t))...);
|
||||
return std::forward<FnT>(__f)(std::get<Idx>(__t)...);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -158,29 +157,29 @@ apply(_Fn&& __f, _Tuple&& __t, impl::index_sequence<_Idx...>)
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// Alias template index_sequence
|
||||
template <size_t... _Idx>
|
||||
using index_sequence = impl::integer_sequence<size_t, _Idx...>;
|
||||
template <size_t... Idx>
|
||||
using index_sequence = impl::integer_sequence<size_t, Idx...>;
|
||||
|
||||
/// Alias template make_index_sequence
|
||||
template <size_t _Num>
|
||||
using make_index_sequence = impl::make_integer_sequence<size_t, _Num>;
|
||||
template <size_t NumT>
|
||||
using make_index_sequence = impl::make_integer_sequence<size_t, NumT>;
|
||||
|
||||
/// Alias template index_sequence_for
|
||||
template <typename... _Types>
|
||||
using index_sequence_for = impl::make_index_sequence<sizeof...(_Types)>;
|
||||
template <typename... Types>
|
||||
using index_sequence_for = impl::make_index_sequence<sizeof...(Types)>;
|
||||
|
||||
template <typename _Fn, typename _Tuple>
|
||||
template <typename FnT, typename TupleT>
|
||||
static inline void
|
||||
apply(_Fn&& __f, _Tuple&& __t)
|
||||
apply(FnT&& __f, TupleT&& __t)
|
||||
{
|
||||
constexpr auto _N = std::tuple_size<_Tuple>::value;
|
||||
impl::apply(std::forward<_Fn>(__f), std::forward<_Tuple>(__t),
|
||||
impl::make_index_sequence<_N>{});
|
||||
constexpr auto N = std::tuple_size<TupleT>::value;
|
||||
impl::apply(std::forward<FnT>(__f), std::forward<TupleT>(__t),
|
||||
impl::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace details
|
||||
} // namespace mpl
|
||||
|
||||
namespace thread_pool
|
||||
{
|
||||
@@ -192,7 +191,6 @@ static const short STOPPED = 2;
|
||||
static const short NONINIT = 3;
|
||||
|
||||
} // namespace state
|
||||
|
||||
} // namespace thread_pool
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
+36
-14
@@ -64,11 +64,11 @@ public:
|
||||
typedef typename base_type::packaged_task_type packaged_task_type;
|
||||
typedef typename base_type::future_type future_type;
|
||||
typedef typename base_type::promise_type promise_type;
|
||||
typedef typename base_type::template JoinFunction<Tp, Arg>::Type join_type;
|
||||
typedef typename JoinFunction<Tp, Arg>::Type join_type;
|
||||
typedef tbb::task_group tbb_task_group_t;
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename... Args>
|
||||
using task_type = Task<ArgTp, Args...>;
|
||||
using task_type = Task<ArgTp, decay_t<Args>...>;
|
||||
//------------------------------------------------------------------------//
|
||||
|
||||
public:
|
||||
@@ -119,36 +119,40 @@ public:
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
task_type<Args...>* wrap(Func&& func, Args&&... args)
|
||||
task_type<Args...>* wrap(Func&& func, Args... args)
|
||||
{
|
||||
return operator+=(new task_type<Args...>(this, std::forward<Func>(func),
|
||||
std::forward<Args>(args)...));
|
||||
return operator+=(
|
||||
new task_type<Args...>(this, std::forward<Func>(func), args...));
|
||||
}
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
void run(Func&& func, Args&&... args)
|
||||
void run(Func&& func, Args... args)
|
||||
{
|
||||
auto _task = wrap(std::forward<Func>(func), std::forward<Args>(args)...);
|
||||
auto _func = [=]() { return func(args...); };
|
||||
auto _task = wrap(std::move(_func));
|
||||
auto _lamb = [=]() { (*_task)(); };
|
||||
m_tbb_task_group->run(_lamb);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
void exec(Func&& func, Args&&... args)
|
||||
void exec(Func&& func, Args... args)
|
||||
{
|
||||
run(std::forward<Func>(func), std::forward<Args>(args)...);
|
||||
auto _func = [=]() { return func(args...); };
|
||||
auto _task = wrap(std::move(_func));
|
||||
auto _lamb = [=]() { (*_task)(); };
|
||||
m_tbb_task_group->run(_lamb);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args, typename Up = Tp,
|
||||
enable_if_t<std::is_same<Up, void>::value, int> = 0>
|
||||
void parallel_for(uintmax_t nitr, uintmax_t, Func&& func, Args&&... args)
|
||||
void parallel_for(uintmax_t nitr, uintmax_t, Func&& func, Args... args)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, nitr),
|
||||
[&](const tbb::blocked_range<size_t>& range) {
|
||||
for(size_t i = range.begin(); i != range.end(); ++i)
|
||||
func(std::forward<Args>(args)...);
|
||||
func(args...);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -175,18 +179,22 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, enable_if_t<!std::is_same<Up, void>::value, int> = 0>
|
||||
template <typename Up = Tp, enable_if_t<!std::is_void<Up>::value, int> = 0>
|
||||
inline Up join(Up accum = {})
|
||||
{
|
||||
this->wait();
|
||||
for(auto& itr : m_task_set)
|
||||
accum = m_join(std::ref(accum), std::forward<ArgTp>(itr.get()));
|
||||
{
|
||||
using RetT = decay_t<decltype(itr.get())>;
|
||||
accum = m_join(std::ref(accum), std::forward<RetT>(itr.get()));
|
||||
}
|
||||
this->clear();
|
||||
return accum;
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, enable_if_t<std::is_same<Up, void>::value, int> = 0>
|
||||
template <typename Up = Tp, typename Rp = Arg,
|
||||
enable_if_t<std::is_void<Up>::value && std::is_void<Rp>::value, int> = 0>
|
||||
inline void join()
|
||||
{
|
||||
this->wait();
|
||||
@@ -195,6 +203,20 @@ public:
|
||||
m_join();
|
||||
this->clear();
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, typename Rp = Arg,
|
||||
enable_if_t<std::is_void<Up>::value && !std::is_void<Rp>::value, int> = 0>
|
||||
inline void join()
|
||||
{
|
||||
this->wait();
|
||||
for(auto& itr : m_task_set)
|
||||
{
|
||||
using RetT = decay_t<decltype(itr.get())>;
|
||||
m_join(std::forward<RetT>(itr.get()));
|
||||
}
|
||||
this->clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Protected variables
|
||||
|
||||
+70
-72
@@ -46,38 +46,38 @@ class ThreadPool;
|
||||
//======================================================================================//
|
||||
|
||||
/// \brief The task class is supplied to thread_pool.
|
||||
template <typename _Ret, typename... _Args>
|
||||
template <typename RetT, typename... Args>
|
||||
class PackagedTask : public VTask
|
||||
{
|
||||
public:
|
||||
typedef PackagedTask<_Ret, _Args...> this_type;
|
||||
typedef std::promise<_Ret> promise_type;
|
||||
typedef std::future<_Ret> future_type;
|
||||
typedef std::packaged_task<_Ret(_Args...)> packaged_task_type;
|
||||
typedef _Ret result_type;
|
||||
typedef std::tuple<_Args...> tuple_type;
|
||||
typedef PackagedTask<RetT, Args...> this_type;
|
||||
typedef std::promise<RetT> promise_type;
|
||||
typedef std::future<RetT> future_type;
|
||||
typedef std::packaged_task<RetT(Args...)> packaged_task_type;
|
||||
typedef RetT result_type;
|
||||
typedef std::tuple<Args...> tuple_type;
|
||||
|
||||
public:
|
||||
// pass a free function pointer
|
||||
template <typename _Func>
|
||||
PackagedTask(_Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
PackagedTask(FuncT&& func, Args... args)
|
||||
: VTask()
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
PackagedTask(VTaskGroup* tg, _Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
PackagedTask(VTaskGroup* tg, FuncT&& func, Args... args)
|
||||
: VTask(tg)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
PackagedTask(ThreadPool* _pool, _Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
PackagedTask(ThreadPool* _pool, FuncT&& func, Args... args)
|
||||
: VTask(_pool)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
virtual ~PackagedTask() {}
|
||||
@@ -86,8 +86,7 @@ public:
|
||||
// execution operator
|
||||
virtual void operator()() override
|
||||
{
|
||||
details::apply(std::forward<packaged_task_type>(m_ptask),
|
||||
std::forward<tuple_type>(m_args));
|
||||
mpl::apply(std::move(m_ptask), std::move(m_args));
|
||||
}
|
||||
future_type get_future() { return m_ptask.get_future(); }
|
||||
virtual bool is_native_task() const override { return true; }
|
||||
@@ -100,37 +99,37 @@ private:
|
||||
//======================================================================================//
|
||||
|
||||
/// \brief The task class is supplied to thread_pool.
|
||||
template <typename _Ret, typename... _Args>
|
||||
template <typename RetT, typename... Args>
|
||||
class Task : public VTask
|
||||
{
|
||||
public:
|
||||
typedef Task<_Ret, _Args...> this_type;
|
||||
typedef std::promise<_Ret> promise_type;
|
||||
typedef std::future<_Ret> future_type;
|
||||
typedef std::packaged_task<_Ret(_Args...)> packaged_task_type;
|
||||
typedef _Ret result_type;
|
||||
typedef std::tuple<_Args...> tuple_type;
|
||||
typedef Task<RetT, Args...> this_type;
|
||||
typedef std::promise<RetT> promise_type;
|
||||
typedef std::future<RetT> future_type;
|
||||
typedef std::packaged_task<RetT(Args...)> packaged_task_type;
|
||||
typedef RetT result_type;
|
||||
typedef std::tuple<Args...> tuple_type;
|
||||
|
||||
public:
|
||||
template <typename _Func>
|
||||
Task(_Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
Task(FuncT&& func, Args... args)
|
||||
: VTask()
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(VTaskGroup* tg, _Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
Task(VTaskGroup* tg, FuncT&& func, Args... args)
|
||||
: VTask(tg)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(ThreadPool* tp, _Func&& func, _Args&&... args)
|
||||
template <typename FuncT>
|
||||
Task(ThreadPool* tp, FuncT&& func, Args... args)
|
||||
: VTask(tp)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_args(std::forward<_Args>(args)...)
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
, m_args(args...)
|
||||
{}
|
||||
|
||||
virtual ~Task() {}
|
||||
@@ -139,8 +138,7 @@ public:
|
||||
// execution operator
|
||||
virtual void operator()() final
|
||||
{
|
||||
details::apply(std::forward<packaged_task_type>(m_ptask),
|
||||
std::forward<tuple_type>(m_args));
|
||||
mpl::apply(std::move(m_ptask), std::move(m_args));
|
||||
// decrements the task-group counter on active tasks
|
||||
// when the counter is < 2, if the thread owning the task group is
|
||||
// sleeping at the TaskGroup::wait(), it signals the thread to wake
|
||||
@@ -160,33 +158,33 @@ private:
|
||||
//======================================================================================//
|
||||
|
||||
/// \brief The task class is supplied to thread_pool.
|
||||
template <typename _Ret>
|
||||
class Task<_Ret, void> : public VTask
|
||||
template <typename RetT>
|
||||
class Task<RetT, void> : public VTask
|
||||
{
|
||||
public:
|
||||
typedef Task<_Ret> this_type;
|
||||
typedef std::promise<_Ret> promise_type;
|
||||
typedef std::future<_Ret> future_type;
|
||||
typedef std::packaged_task<_Ret()> packaged_task_type;
|
||||
typedef _Ret result_type;
|
||||
typedef Task<RetT> this_type;
|
||||
typedef std::promise<RetT> promise_type;
|
||||
typedef std::future<RetT> future_type;
|
||||
typedef std::packaged_task<RetT()> packaged_task_type;
|
||||
typedef RetT result_type;
|
||||
|
||||
public:
|
||||
template <typename _Func>
|
||||
Task(_Func&& func)
|
||||
template <typename FuncT>
|
||||
Task(FuncT&& func)
|
||||
: VTask()
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(VTaskGroup* tg, _Func&& func)
|
||||
template <typename FuncT>
|
||||
Task(VTaskGroup* tg, FuncT&& func)
|
||||
: VTask(tg)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(ThreadPool* tp, _Func&& func)
|
||||
template <typename FuncT>
|
||||
Task(ThreadPool* tp, FuncT&& func)
|
||||
: VTask(tp)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
virtual ~Task() {}
|
||||
@@ -218,30 +216,30 @@ template <>
|
||||
class Task<void, void> : public VTask
|
||||
{
|
||||
public:
|
||||
typedef void _Ret;
|
||||
typedef void RetT;
|
||||
typedef Task<void, void> this_type;
|
||||
typedef std::promise<_Ret> promise_type;
|
||||
typedef std::future<_Ret> future_type;
|
||||
typedef std::packaged_task<_Ret()> packaged_task_type;
|
||||
typedef _Ret result_type;
|
||||
typedef std::promise<RetT> promise_type;
|
||||
typedef std::future<RetT> future_type;
|
||||
typedef std::packaged_task<RetT()> packaged_task_type;
|
||||
typedef RetT result_type;
|
||||
|
||||
public:
|
||||
template <typename _Func>
|
||||
explicit Task(_Func&& func)
|
||||
template <typename FuncT>
|
||||
explicit Task(FuncT&& func)
|
||||
: VTask()
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(VTaskGroup* tg, _Func&& func)
|
||||
template <typename FuncT>
|
||||
Task(VTaskGroup* tg, FuncT&& func)
|
||||
: VTask(tg)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
template <typename _Func>
|
||||
Task(ThreadPool* tp, _Func&& func)
|
||||
template <typename FuncT>
|
||||
Task(ThreadPool* tp, FuncT&& func)
|
||||
: VTask(tp)
|
||||
, m_ptask(std::forward<_Func>(func))
|
||||
, m_ptask(std::forward<FuncT>(func))
|
||||
{}
|
||||
|
||||
virtual ~Task() {}
|
||||
|
||||
+115
-74
@@ -51,70 +51,97 @@ class ThreadPool;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(PTL_DEFAULT_OBJECT)
|
||||
# define PTL_DEFAULT_OBJECT(NAME) \
|
||||
NAME() = default; \
|
||||
~NAME() = default; \
|
||||
NAME(const NAME&) = default; \
|
||||
NAME(NAME&&) noexcept = default; \
|
||||
NAME& operator=(const NAME&) = default; \
|
||||
NAME& operator=(NAME&&) noexcept = default;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename JoinT, typename JoinArg>
|
||||
struct JoinFunction
|
||||
{
|
||||
public:
|
||||
using Type = std::function<JoinT(JoinT&, JoinArg&&)>;
|
||||
|
||||
public:
|
||||
PTL_DEFAULT_OBJECT(JoinFunction)
|
||||
|
||||
template <typename Func>
|
||||
JoinFunction(Func&& func)
|
||||
: m_func(std::forward<Func>(func))
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
JoinT& operator()(Args&&... args)
|
||||
{
|
||||
return std::move(m_func(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_func = [](JoinT& lhs, JoinArg&&) { return lhs; };
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename JoinArg>
|
||||
struct JoinFunction<void, JoinArg>
|
||||
{
|
||||
public:
|
||||
using Type = std::function<void(JoinArg)>;
|
||||
|
||||
public:
|
||||
PTL_DEFAULT_OBJECT(JoinFunction)
|
||||
|
||||
template <typename Func>
|
||||
JoinFunction(Func&& func)
|
||||
: m_func(std::forward<Func>(func))
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
void operator()(Args&&... args)
|
||||
{
|
||||
m_func(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_func = [](JoinArg) {};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <>
|
||||
struct JoinFunction<void, void>
|
||||
{
|
||||
public:
|
||||
using Type = std::function<void()>;
|
||||
|
||||
public:
|
||||
PTL_DEFAULT_OBJECT(JoinFunction)
|
||||
|
||||
template <typename Func>
|
||||
JoinFunction(Func&& func)
|
||||
: m_func(std::forward<Func>(func))
|
||||
{}
|
||||
|
||||
void operator()() { m_func(); }
|
||||
|
||||
private:
|
||||
Type m_func = []() {};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename Arg = Tp>
|
||||
class TaskGroup
|
||||
: public VTaskGroup
|
||||
, public TaskAllocator<TaskGroup<Tp, Arg>>
|
||||
{
|
||||
protected:
|
||||
//----------------------------------------------------------------------------------//
|
||||
template <typename JoinT, typename JoinArg>
|
||||
struct JoinFunction
|
||||
{
|
||||
public:
|
||||
typedef std::function<JoinT(JoinT&, JoinArg&&)> Type;
|
||||
|
||||
public:
|
||||
JoinFunction() = default;
|
||||
~JoinFunction() = default;
|
||||
JoinFunction(const JoinFunction&) = default;
|
||||
JoinFunction(JoinFunction&&) = default;
|
||||
|
||||
JoinFunction& operator=(const JoinFunction&) = default;
|
||||
JoinFunction& operator=(JoinFunction&&) = default;
|
||||
|
||||
template <typename Func>
|
||||
JoinFunction(Func&& func)
|
||||
: m_func(std::forward<Func>(func))
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
JoinT& operator()(Args&&... args)
|
||||
{
|
||||
return std::move(m_func(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_func = [](JoinT& lhs, JoinArg&&) { return lhs; };
|
||||
};
|
||||
//----------------------------------------------------------------------------------//
|
||||
template <typename JoinArg>
|
||||
struct JoinFunction<void, JoinArg>
|
||||
{
|
||||
public:
|
||||
typedef std::function<void()> Type;
|
||||
|
||||
public:
|
||||
JoinFunction() = default;
|
||||
~JoinFunction() = default;
|
||||
JoinFunction(const JoinFunction&) = default;
|
||||
JoinFunction(JoinFunction&&) = default;
|
||||
|
||||
JoinFunction& operator=(const JoinFunction&) = default;
|
||||
JoinFunction& operator=(JoinFunction&&) = default;
|
||||
|
||||
template <typename Func>
|
||||
JoinFunction(Func&& func)
|
||||
: m_func(std::forward<Func>(func))
|
||||
{}
|
||||
|
||||
void operator()() { m_func(); }
|
||||
|
||||
private:
|
||||
Type m_func = []() {};
|
||||
};
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
typedef decay_t<Arg> ArgTp;
|
||||
@@ -131,7 +158,7 @@ public:
|
||||
typedef typename task_list_t::const_reverse_iterator const_reverse_iterator;
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename... Args>
|
||||
using task_type = Task<ArgTp, Args...>;
|
||||
using task_type = Task<ArgTp, decay_t<Args>...>;
|
||||
//------------------------------------------------------------------------//
|
||||
|
||||
public:
|
||||
@@ -176,29 +203,29 @@ public:
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
task_type<Args...>* wrap(Func&& func, Args&&... args)
|
||||
task_type<Args...>* wrap(Func&& func, Args... args)
|
||||
{
|
||||
return operator+=(new task_type<Args...>(this, std::forward<Func>(func),
|
||||
std::forward<Args>(args)...));
|
||||
return operator+=(
|
||||
new task_type<Args...>(this, std::forward<Func>(func), args...));
|
||||
}
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
void exec(Func&& func, Args&&... args)
|
||||
void exec(Func&& func, Args... args)
|
||||
{
|
||||
m_pool->add_task(wrap(std::forward<Func>(func), std::forward<Args>(args)...));
|
||||
m_pool->add_task(wrap(std::forward<Func>(func), args...));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
void run(Func&& func, Args&&... args)
|
||||
void run(Func&& func, Args... args)
|
||||
{
|
||||
m_pool->add_task(wrap(std::forward<Func>(func), std::forward<Args>(args)...));
|
||||
m_pool->add_task(wrap(std::forward<Func>(func), args...));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename Func, typename... Args>
|
||||
void parallel_for(const intmax_t& nitr, const intmax_t& chunks, Func&& func,
|
||||
Args&&... args)
|
||||
Args... args)
|
||||
{
|
||||
auto nsplit = nitr / chunks;
|
||||
auto nmod = nitr % chunks;
|
||||
@@ -208,8 +235,7 @@ public:
|
||||
{
|
||||
auto _beg = n * chunks;
|
||||
auto _end = (n + 1) * chunks + ((n + 1 == nsplit) ? nmod : 0);
|
||||
run(std::forward<Func>(func), std::move(_beg), std::move(_end),
|
||||
std::forward<Args>(args)...);
|
||||
run(std::forward<Func>(func), std::move(_beg), std::move(_end), args...);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,21 +270,22 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, enable_if_t<!std::is_same<Up, void>::value, int> = 0>
|
||||
template <typename Up = Tp, enable_if_t<!std::is_void<Up>::value, int> = 0>
|
||||
inline Up join(Up accum = {})
|
||||
{
|
||||
this->wait();
|
||||
for(auto& itr : m_task_set)
|
||||
{
|
||||
using RetType = decltype(itr.get());
|
||||
accum = std::move(m_join(std::ref(accum), std::forward<RetType>(itr.get())));
|
||||
using RetT = decay_t<decltype(itr.get())>;
|
||||
accum = std::move(m_join(std::ref(accum), std::forward<RetT>(itr.get())));
|
||||
}
|
||||
this->clear();
|
||||
return accum;
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, enable_if_t<std::is_same<Up, void>::value, int> = 0>
|
||||
template <typename Up = Tp, typename Rp = Arg,
|
||||
enable_if_t<std::is_void<Up>::value && std::is_void<Rp>::value, int> = 0>
|
||||
inline void join()
|
||||
{
|
||||
this->wait();
|
||||
@@ -268,6 +295,20 @@ public:
|
||||
this->clear();
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// wait to finish
|
||||
template <typename Up = Tp, typename Rp = Arg,
|
||||
enable_if_t<std::is_void<Up>::value && !std::is_void<Rp>::value, int> = 0>
|
||||
inline void join()
|
||||
{
|
||||
this->wait();
|
||||
for(auto& itr : m_task_set)
|
||||
{
|
||||
using RetT = decay_t<decltype(itr.get())>;
|
||||
m_join(std::forward<RetT>(itr.get()));
|
||||
}
|
||||
this->clear();
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// clear the task result history
|
||||
void clear()
|
||||
{
|
||||
|
||||
+58
-59
@@ -30,6 +30,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PTL/Globals.hh"
|
||||
#include "PTL/TBBTaskGroup.hh"
|
||||
#include "PTL/Task.hh"
|
||||
#include "PTL/TaskGroup.hh"
|
||||
@@ -52,9 +53,6 @@ public:
|
||||
typedef TaskManager this_type;
|
||||
typedef ThreadPool::size_type size_type;
|
||||
|
||||
template <bool _Bp, typename _Tp = void>
|
||||
using enable_if_t = typename std::enable_if<_Bp, _Tp>::type;
|
||||
|
||||
public:
|
||||
// Constructor and Destructors
|
||||
explicit TaskManager(ThreadPool*);
|
||||
@@ -89,8 +87,8 @@ public:
|
||||
//------------------------------------------------------------------------//
|
||||
// direct insertion of a task
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename... _Args>
|
||||
void exec(Task<_Args...>* _task)
|
||||
template <typename... Args>
|
||||
void exec(Task<Args...>* _task)
|
||||
{
|
||||
m_pool->add_task(_task);
|
||||
}
|
||||
@@ -98,39 +96,40 @@ public:
|
||||
//------------------------------------------------------------------------//
|
||||
// direct insertion of a packaged_task
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Func, typename... _Args>
|
||||
std::future<_Ret> async(_Func&& func, _Args&&... args)
|
||||
template <typename RetT, typename FuncT, typename... Args>
|
||||
std::future<RetT> async(FuncT&& func, Args&&... args)
|
||||
{
|
||||
typedef PackagedTask<_Ret, _Args...> task_type;
|
||||
typedef PackagedTask<RetT, Args...> task_type;
|
||||
typedef task_type* task_pointer;
|
||||
|
||||
task_pointer _ptask =
|
||||
new task_type(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
std::future<_Ret> _f = _ptask->get_future();
|
||||
new task_type(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
std::future<RetT> _f = _ptask->get_future();
|
||||
m_pool->add_task(_ptask);
|
||||
return _f;
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Func>
|
||||
std::future<_Ret> async(_Func&& func)
|
||||
template <typename RetT, typename FuncT>
|
||||
std::future<RetT> async(FuncT&& func)
|
||||
{
|
||||
typedef PackagedTask<_Ret> task_type;
|
||||
typedef PackagedTask<RetT> task_type;
|
||||
typedef task_type* task_pointer;
|
||||
|
||||
task_pointer _ptask = new task_type(std::forward<_Func>(func));
|
||||
std::future<_Ret> _f = _ptask->get_future();
|
||||
task_pointer _ptask = new task_type(std::forward<FuncT>(func));
|
||||
std::future<RetT> _f = _ptask->get_future();
|
||||
m_pool->add_task(_ptask);
|
||||
return _f;
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Func, typename... _Args,
|
||||
typename _Ret = typename std::result_of<_Func(_Args&&...)>::type>
|
||||
auto async(_Func&& func, _Args&&... args) -> std::future<_Ret>
|
||||
template <typename FuncT, typename... Args>
|
||||
auto async(FuncT&& func, Args... args)
|
||||
-> std::future<decay_t<decltype(func(args...))>>
|
||||
{
|
||||
typedef PackagedTask<_Ret, _Args...> task_type;
|
||||
using RetT = decay_t<decltype(func(args...))>;
|
||||
typedef PackagedTask<RetT, Args...> task_type;
|
||||
|
||||
auto _ptask =
|
||||
new task_type(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
new task_type(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
auto _f = _ptask->get_future();
|
||||
m_pool->add_task(_ptask);
|
||||
return _f;
|
||||
@@ -141,59 +140,59 @@ public:
|
||||
//------------------------------------------------------------------------//
|
||||
// public wrap functions
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func, typename... _Args>
|
||||
Task<_Ret, _Arg, _Args...>* wrap(TaskGroup<_Ret, _Arg>& tg, _Func&& func,
|
||||
_Args&&... args)
|
||||
template <typename RetT, typename ArgT, typename FuncT, typename... Args>
|
||||
Task<RetT, ArgT, Args...>* wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func,
|
||||
Args&&... args)
|
||||
{
|
||||
return tg.wrap(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func>
|
||||
Task<_Ret, _Arg>* wrap(TaskGroup<_Ret, _Arg>& tg, _Func&& func)
|
||||
template <typename RetT, typename ArgT, typename FuncT>
|
||||
Task<RetT, ArgT>* wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
|
||||
{
|
||||
return tg.wrap(std::forward<_Func>(func));
|
||||
return tg.wrap(std::forward<FuncT>(func));
|
||||
}
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------------//
|
||||
// public exec functions
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func, typename... _Args>
|
||||
void exec(TaskGroup<_Ret, _Arg>& tg, _Func&& func, _Args&&... args)
|
||||
template <typename RetT, typename ArgT, typename FuncT, typename... Args>
|
||||
void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func>
|
||||
void exec(TaskGroup<_Ret, _Arg>& tg, _Func&& func)
|
||||
template <typename RetT, typename ArgT, typename FuncT>
|
||||
void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func));
|
||||
tg.exec(std::forward<FuncT>(func));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func, typename... _Args>
|
||||
void rexec(TaskGroup<_Ret, _Arg>& tg, _Func&& func, _Args&&... args)
|
||||
template <typename RetT, typename ArgT, typename FuncT, typename... Args>
|
||||
void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func>
|
||||
void rexec(TaskGroup<_Ret, _Arg>& tg, _Func&& func)
|
||||
template <typename RetT, typename ArgT, typename FuncT>
|
||||
void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func));
|
||||
tg.exec(std::forward<FuncT>(func));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
// public exec functions (void specializations)
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Func, typename... _Args>
|
||||
void rexec(TaskGroup<void, void>& tg, _Func&& func, _Args&&... args)
|
||||
template <typename FuncT, typename... Args>
|
||||
void rexec(TaskGroup<void, void>& tg, FuncT&& func, Args&&... args)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Func>
|
||||
void rexec(TaskGroup<void, void>& tg, _Func&& func)
|
||||
template <typename FuncT>
|
||||
void rexec(TaskGroup<void, void>& tg, FuncT&& func)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func));
|
||||
tg.exec(std::forward<FuncT>(func));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
|
||||
@@ -201,39 +200,39 @@ public:
|
||||
//------------------------------------------------------------------------//
|
||||
// public wrap functions using TBB tasks
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func, typename... _Args>
|
||||
Task<_Ret, _Arg, _Args...>* wrap(TBBTaskGroup<_Ret, _Arg>& tg, _Func&& func,
|
||||
_Args&&... args)
|
||||
template <typename RetT, typename ArgT, typename FuncT, typename... Args>
|
||||
Task<RetT, ArgT, Args...>* wrap(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func,
|
||||
Args&&... args)
|
||||
{
|
||||
return tg.wrap(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func>
|
||||
Task<_Ret, _Arg>* wrap(TBBTaskGroup<_Ret, _Arg>& tg, _Func&& func)
|
||||
template <typename RetT, typename ArgT, typename FuncT>
|
||||
Task<RetT, ArgT>* wrap(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func)
|
||||
{
|
||||
return tg.wrap(std::forward<_Func>(func));
|
||||
return tg.wrap(std::forward<FuncT>(func));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------//
|
||||
// public exec functions using TBB tasks
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func, typename... _Args>
|
||||
void exec(TBBTaskGroup<_Ret, _Arg>& tg, _Func&& func, _Args&&... args)
|
||||
template <typename RetT, typename ArgT, typename FuncT, typename... Args>
|
||||
void exec(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func), std::forward<_Args>(args)...);
|
||||
tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
template <typename _Ret, typename _Arg, typename _Func>
|
||||
void exec(TBBTaskGroup<_Ret, _Arg>& tg, _Func&& func)
|
||||
template <typename RetT, typename ArgT, typename FuncT>
|
||||
void exec(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func)
|
||||
{
|
||||
tg.exec(std::forward<_Func>(func));
|
||||
tg.exec(std::forward<FuncT>(func));
|
||||
}
|
||||
//------------------------------------------------------------------------//
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Protected variables
|
||||
ThreadPool* m_pool;
|
||||
ThreadPool* m_pool = nullptr;
|
||||
|
||||
private:
|
||||
static TaskManager*& fgInstance();
|
||||
|
||||
@@ -44,8 +44,6 @@ class TaskManager;
|
||||
class TaskRunManager
|
||||
{
|
||||
public:
|
||||
typedef TaskGroup<void> RunTaskGroup;
|
||||
typedef TBBTaskGroup<void> RunTaskGroupTBB;
|
||||
typedef TaskRunManager* pointer;
|
||||
|
||||
public:
|
||||
|
||||
+6
-6
@@ -55,14 +55,14 @@ public:
|
||||
// dummy wait
|
||||
inline void wait() {}
|
||||
// run function
|
||||
template <typename _Func>
|
||||
inline void run(_Func f)
|
||||
template <typename FuncT>
|
||||
inline void run(FuncT f)
|
||||
{
|
||||
f();
|
||||
}
|
||||
// run and wait
|
||||
template <typename _Func>
|
||||
inline void run_and_wait(_Func f)
|
||||
template <typename FuncT>
|
||||
inline void run_and_wait(FuncT f)
|
||||
{
|
||||
f();
|
||||
}
|
||||
@@ -99,8 +99,8 @@ class VUserTaskQueue;
|
||||
class ThreadData
|
||||
{
|
||||
public:
|
||||
template <typename _Tp>
|
||||
using TaskStack = std::deque<_Tp>;
|
||||
template <typename Tp>
|
||||
using TaskStack = std::deque<Tp>;
|
||||
|
||||
ThreadData(ThreadPool* tp);
|
||||
~ThreadData();
|
||||
|
||||
+128
-11
@@ -53,6 +53,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -62,8 +63,8 @@ namespace PTL
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
template <typename _KeyType, typename _MappedType, typename _HashType = _KeyType>
|
||||
using uomap = std::unordered_map<_KeyType, _MappedType, std::hash<_HashType>>;
|
||||
template <typename KeyT, typename MappedT, typename HashT = KeyT>
|
||||
using uomap = std::unordered_map<KeyT, MappedT, std::hash<HashT>>;
|
||||
|
||||
// pod-types
|
||||
using size_type = size_t;
|
||||
@@ -82,8 +83,9 @@ public:
|
||||
typedef std::vector<bool> bool_list_t;
|
||||
typedef std::map<ThreadId, uintmax_t> thread_id_map_t;
|
||||
typedef std::map<uintmax_t, ThreadId> thread_index_map_t;
|
||||
typedef std::function<void()> initialize_func_t;
|
||||
using thread_vec_t = std::vector<Thread>;
|
||||
// functions
|
||||
typedef std::function<void()> initialize_func_t;
|
||||
typedef std::function<intmax_t(intmax_t)> affinity_func_t;
|
||||
|
||||
public:
|
||||
@@ -110,6 +112,9 @@ public:
|
||||
size_type destroy_threadpool(); // destroy the threads
|
||||
size_type stop_thread();
|
||||
|
||||
template <typename FuncT>
|
||||
void execute_on_all_threads(FuncT&& _func);
|
||||
|
||||
public:
|
||||
// Public functions related to TBB
|
||||
static bool using_tbb();
|
||||
@@ -121,8 +126,8 @@ public:
|
||||
size_type add_task(task_pointer task, int bin = -1);
|
||||
// size_type add_thread_task(ThreadId id, task_pointer&& task);
|
||||
// add a generic container with iterator
|
||||
template <typename _List_t>
|
||||
size_type add_tasks(_List_t&);
|
||||
template <typename ListT>
|
||||
size_type add_tasks(ListT&);
|
||||
|
||||
Thread* get_thread(size_type _n) const;
|
||||
Thread* get_thread(std::thread::id id) const;
|
||||
@@ -161,14 +166,14 @@ public:
|
||||
void set_affinity(affinity_func_t f) { m_affinity_func = f; }
|
||||
void set_affinity(intmax_t i, Thread&);
|
||||
|
||||
void SetVerbose(int n) { m_verbose = n; }
|
||||
int GetVerbose() const { return m_verbose; }
|
||||
void set_verbose(int n) { m_verbose = n; }
|
||||
int get_verbose() const { return m_verbose; }
|
||||
bool is_master() const { return ThisThread::get_id() == m_master_tid; }
|
||||
|
||||
public:
|
||||
// read FORCE_NUM_THREADS environment variable
|
||||
static const thread_id_map_t& GetThreadIDs();
|
||||
static uintmax_t GetThisThreadID();
|
||||
static const thread_id_map_t& get_thread_ids();
|
||||
static uintmax_t get_this_thread_id();
|
||||
|
||||
protected:
|
||||
void execute_thread(VUserTaskQueue*); // function thread sits in
|
||||
@@ -214,6 +219,7 @@ private:
|
||||
bool_list_t m_is_stopped; // lets thread know to stop
|
||||
thread_list_t m_main_threads; // storage for active threads
|
||||
thread_list_t m_stop_threads; // storage for stopped threads
|
||||
thread_vec_t m_threads;
|
||||
|
||||
// task queue
|
||||
task_queue_t* m_task_queue;
|
||||
@@ -332,9 +338,9 @@ ThreadPool::add_task(task_pointer task, int bin)
|
||||
return static_cast<size_type>(insert(task, bin));
|
||||
}
|
||||
//--------------------------------------------------------------------------------------//
|
||||
template <typename _List_t>
|
||||
template <typename ListT>
|
||||
inline ThreadPool::size_type
|
||||
ThreadPool::add_tasks(_List_t& c)
|
||||
ThreadPool::add_tasks(ListT& c)
|
||||
{
|
||||
if(!m_alive_flag) // if we haven't built thread-pool, just execute
|
||||
{
|
||||
@@ -363,6 +369,117 @@ ThreadPool::add_tasks(_List_t& c)
|
||||
|
||||
return c_size;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------//
|
||||
template <typename FuncT>
|
||||
inline void
|
||||
ThreadPool::execute_on_all_threads(FuncT&& _func)
|
||||
{
|
||||
if(m_tbb_tp && m_tbb_task_group)
|
||||
{
|
||||
#if defined(PTL_USE_TBB)
|
||||
// TBB lazily activates threads to process tasks and the master thread
|
||||
// participates in processing the tasks so getting a specific
|
||||
// function to execute only on the worker threads requires some trickery
|
||||
//
|
||||
auto master_tid = ThisThread::get_id();
|
||||
std::set<std::thread::id> _first;
|
||||
Mutex _mutex;
|
||||
// init function which executes function and returns 1 only once
|
||||
auto _init = [&]() {
|
||||
static thread_local int _once = 0;
|
||||
_mutex.lock();
|
||||
if(_first.find(std::this_thread::get_id()) == _first.end())
|
||||
{
|
||||
// we need to reset this thread-local static for multiple invocations
|
||||
// of the same template instantiation
|
||||
_once = 0;
|
||||
_first.insert(std::this_thread::get_id());
|
||||
}
|
||||
_mutex.unlock();
|
||||
if(_once++ == 0)
|
||||
{
|
||||
_func();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
// consumes approximately N milliseconds of cpu time
|
||||
auto _consume = [](long n) {
|
||||
using stl_mutex_t = std::mutex;
|
||||
using unique_lock_t = std::unique_lock<stl_mutex_t>;
|
||||
// a mutex held by one lock
|
||||
stl_mutex_t mutex;
|
||||
// acquire lock
|
||||
unique_lock_t hold_lk(mutex);
|
||||
// associate but defer
|
||||
unique_lock_t try_lk(mutex, std::defer_lock);
|
||||
// get current time
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
// try until time point
|
||||
while(std::chrono::steady_clock::now() < (now + std::chrono::milliseconds(n)))
|
||||
try_lk.try_lock();
|
||||
};
|
||||
// this will collect the number of threads which have
|
||||
// executed the _init function above
|
||||
std::atomic<size_t> _total_init{ 0 };
|
||||
// this is the task passed to the task-group
|
||||
auto _init_task = [&]() {
|
||||
int _ret = 0;
|
||||
// don't let the master thread execute the function
|
||||
if(ThisThread::get_id() != master_tid)
|
||||
{
|
||||
// execute the function
|
||||
_ret = _init();
|
||||
// add the result
|
||||
_total_init += _ret;
|
||||
}
|
||||
// if the function did not return anything, put it to sleep
|
||||
// so TBB will wake other threads to execute the remaining tasks
|
||||
if(_ret == 0)
|
||||
_consume(100);
|
||||
};
|
||||
|
||||
// TBB won't oversubscribe so we need to limit by ncores - 1
|
||||
size_t nitr = 0;
|
||||
size_t _maxp = tbb_global_control()->active_value(
|
||||
tbb::global_control::max_allowed_parallelism);
|
||||
size_t _sz = size();
|
||||
size_t _ncore = Threading::GetNumberOfCores() - 1;
|
||||
size_t _num = std::min(_maxp, std::min(_sz, _ncore));
|
||||
auto _fname = __FUNCTION__;
|
||||
auto _write_info = [&]() {
|
||||
std::cerr << "[" << _fname << "]> Total initalized: " << _total_init
|
||||
<< ", expected: " << _num << ", max-parallel: " << _maxp
|
||||
<< ", size: " << _sz << ", ncore: " << _ncore << std::endl;
|
||||
};
|
||||
while(_total_init < _num)
|
||||
{
|
||||
auto _n = _num;
|
||||
while(--_n > 0)
|
||||
m_tbb_task_group->run(_init_task);
|
||||
m_tbb_task_group->wait();
|
||||
// don't loop infinitely but use a strict condition
|
||||
if(nitr++ > 2 * (_num + 1) && (_total_init - 1) == _num)
|
||||
{
|
||||
_write_info();
|
||||
break;
|
||||
}
|
||||
// at this point we need to exit
|
||||
if(nitr > 4 * (_ncore + 1))
|
||||
{
|
||||
_write_info();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(get_verbose() > 3)
|
||||
_write_info();
|
||||
#endif
|
||||
}
|
||||
else if(get_queue())
|
||||
{
|
||||
get_queue()->ExecuteOnAllThreads(this, std::forward<FuncT>(_func));
|
||||
}
|
||||
}
|
||||
//======================================================================================//
|
||||
|
||||
} // namespace PTL
|
||||
|
||||
+17
-17
@@ -42,12 +42,12 @@ namespace PTL
|
||||
#define THREADSLEEP(tick) std::this_thread::sleep_for(std::chrono::seconds(tick))
|
||||
|
||||
// will be used in the future when migrating threading to task-based style
|
||||
template <typename _Tp>
|
||||
using Future = std::future<_Tp>;
|
||||
template <typename _Tp>
|
||||
using SharedFuture = std::shared_future<_Tp>;
|
||||
template <typename _Tp>
|
||||
using Promise = std::promise<_Tp>;
|
||||
template <typename Tp>
|
||||
using Future = std::future<Tp>;
|
||||
template <typename Tp>
|
||||
using SharedFuture = std::shared_future<Tp>;
|
||||
template <typename Tp>
|
||||
using Promise = std::promise<Tp>;
|
||||
|
||||
//
|
||||
// NOTE ON Tasking SERIAL BUILDS AND MUTEX/UNIQUE_LOCK
|
||||
@@ -94,12 +94,12 @@ using namespace std::this_thread;
|
||||
|
||||
// will be used in the future when migrating threading to task-based style
|
||||
// and are currently used in unit tests
|
||||
template <typename _Tp>
|
||||
using Promise = std::promise<_Tp>;
|
||||
template <typename _Tp>
|
||||
using Future = std::future<_Tp>;
|
||||
template <typename _Tp>
|
||||
using SharedFuture = std::shared_future<_Tp>;
|
||||
template <typename Tp>
|
||||
using Promise = std::promise<Tp>;
|
||||
template <typename Tp>
|
||||
using Future = std::future<Tp>;
|
||||
template <typename Tp>
|
||||
using SharedFuture = std::shared_future<Tp>;
|
||||
|
||||
// Some useful types
|
||||
typedef void* ThreadFunReturnType;
|
||||
@@ -113,7 +113,7 @@ typedef int (*thread_unlock)(Mutex*);
|
||||
// a template class "Cache<T>" that required a static
|
||||
// mutex for specific to type T:
|
||||
// AutoLock l(TypeMutex<Cache<T>>());
|
||||
template <typename _Tp>
|
||||
template <typename Tp>
|
||||
Mutex&
|
||||
TypeMutex(const unsigned int& _n = 0)
|
||||
{
|
||||
@@ -135,7 +135,7 @@ TypeMutex(const unsigned int& _n = 0)
|
||||
// a template class "Cache<T>" that required a static
|
||||
// recursive_mutex for specific to type T:
|
||||
// RecursiveAutoLock l(TypeRecursiveMutex<Cache<T>>());
|
||||
template <typename _Tp>
|
||||
template <typename Tp>
|
||||
RecursiveMutex&
|
||||
TypeRecursiveMutex(const unsigned int& _n = 0)
|
||||
{
|
||||
@@ -175,11 +175,11 @@ typedef std::thread::id Pid_t;
|
||||
|
||||
// Instead of previous macro taking one argument, define function taking
|
||||
// unlimited arguments
|
||||
template <typename _Worker, typename _Func, typename... _Args>
|
||||
template <typename WorkerT, typename FuncT, typename... Args>
|
||||
void
|
||||
THREADCREATE(_Worker*& worker, _Func func, _Args... args)
|
||||
THREADCREATE(WorkerT*& worker, FuncT func, Args... args)
|
||||
{
|
||||
*worker = Thread(func, std::forward<_Args>(args)...);
|
||||
*worker = Thread(func, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Conditions
|
||||
|
||||
+23
-23
@@ -25,10 +25,10 @@
|
||||
|
||||
namespace PTL
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
template <typename Tp, typename Up>
|
||||
struct SmallerThanT
|
||||
{
|
||||
static constexpr bool value = sizeof(_Tp) < sizeof(_Up);
|
||||
static constexpr bool value = sizeof(Tp) < sizeof(Up);
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
@@ -38,54 +38,54 @@ struct SmallerThanT
|
||||
// useful to work with sequences of compile-time values, such as the bounds of a
|
||||
// multidimensional array or indices into another typelist.
|
||||
|
||||
template <typename _Tp, _Tp Value>
|
||||
template <typename Tp, Tp Value>
|
||||
struct CTValue
|
||||
{
|
||||
static constexpr _Tp value = Value;
|
||||
static constexpr Tp value = Value;
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
template <std::size_t Height, typename _Tp,
|
||||
bool = std::is_class<_Tp>::value && !std::is_final<_Tp>::value>
|
||||
template <std::size_t Height, typename Tp,
|
||||
bool = std::is_class<Tp>::value && !std::is_final<Tp>::value>
|
||||
class TupleElt;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// specialization that does not satisfy is_class<> and not is_final<>
|
||||
//
|
||||
template <std::size_t Height, typename _Tp>
|
||||
class TupleElt<Height, _Tp, false>
|
||||
template <std::size_t Height, typename Tp>
|
||||
class TupleElt<Height, Tp, false>
|
||||
{
|
||||
_Tp value;
|
||||
Tp value;
|
||||
|
||||
public:
|
||||
TupleElt() = default;
|
||||
|
||||
template <typename _Up>
|
||||
TupleElt(_Up&& other)
|
||||
: value(std::forward<_Up>(other))
|
||||
template <typename Up>
|
||||
TupleElt(Up&& other)
|
||||
: value(std::forward<Up>(other))
|
||||
{}
|
||||
|
||||
_Tp& get() { return value; }
|
||||
_Tp const& get() const { return value; }
|
||||
Tp& get() { return value; }
|
||||
Tp const& get() const { return value; }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// specialization that does satisfy is_class<> and not is_final<>
|
||||
//
|
||||
template <std::size_t Height, typename _Tp>
|
||||
class TupleElt<Height, _Tp, true> : private _Tp
|
||||
template <std::size_t Height, typename Tp>
|
||||
class TupleElt<Height, Tp, true> : private Tp
|
||||
{
|
||||
public:
|
||||
TupleElt() = default;
|
||||
|
||||
template <typename _Up>
|
||||
explicit TupleElt(_Up&& other)
|
||||
: _Tp(std::forward<_Up>(other))
|
||||
template <typename Up>
|
||||
explicit TupleElt(Up&& other)
|
||||
: Tp(std::forward<Up>(other))
|
||||
{}
|
||||
|
||||
_Tp& get() { return *this; }
|
||||
const _Tp& get() const { return *this; }
|
||||
Tp& get() { return *this; }
|
||||
const Tp& get() const { return *this; }
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
@@ -141,8 +141,8 @@ get(Tuple<Elements...>& t) -> decltype(get_height<sizeof...(Elements) - I - 1>(t
|
||||
return get_height<sizeof...(Elements) - I - 1>(t);
|
||||
}
|
||||
|
||||
template <typename... _Tp>
|
||||
using TypeList = Tuple<_Tp...>;
|
||||
template <typename... Tp>
|
||||
using TypeList = Tuple<Tp...>;
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
|
||||
+4
-4
@@ -126,15 +126,15 @@ public:
|
||||
static void set_max_depth(const int64_t& val) { fmax_depth = val; }
|
||||
static bool is_enabled() { return fenabled; }
|
||||
|
||||
template <typename _Tp = CountedType,
|
||||
typename std::enable_if<std::is_same<_Tp, void>::value>::type* = nullptr>
|
||||
template <typename Tp = CountedType,
|
||||
typename std::enable_if<std::is_same<Tp, void>::value>::type* = nullptr>
|
||||
static bool enable()
|
||||
{
|
||||
return fenabled && fmax_depth > count();
|
||||
}
|
||||
// the void type is consider the global setting
|
||||
template <typename _Tp = CountedType,
|
||||
typename std::enable_if<!std::is_same<_Tp, void>::value>::type* = nullptr>
|
||||
template <typename Tp = CountedType,
|
||||
typename std::enable_if<!std::is_same<Tp, void>::value>::type* = nullptr>
|
||||
static bool enable()
|
||||
{
|
||||
return void_type::is_enabled() && void_type::max_depth() > count() && fenabled &&
|
||||
|
||||
+32
-32
@@ -39,20 +39,20 @@ namespace PTL
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// use this function to get rid of "unused parameter" warnings
|
||||
//
|
||||
template <typename... _Args>
|
||||
template <typename... Args>
|
||||
void
|
||||
ConsumeParameters(_Args...)
|
||||
ConsumeParameters(Args...)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// a non-string environment option with a string identifier
|
||||
template <typename _Tp>
|
||||
using EnvChoice = std::tuple<_Tp, std::string, std::string>;
|
||||
template <typename Tp>
|
||||
using EnvChoice = std::tuple<Tp, std::string, std::string>;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// list of environment choices with non-string and string identifiers
|
||||
template <typename _Tp>
|
||||
using EnvChoiceList = std::set<EnvChoice<_Tp>>;
|
||||
template <typename Tp>
|
||||
using EnvChoiceList = std::set<EnvChoice<Tp>>;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
@@ -72,8 +72,8 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename _Tp>
|
||||
void insert(const std::string& env_id, _Tp val)
|
||||
template <typename Tp>
|
||||
void insert(const std::string& env_id, Tp val)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::boolalpha << val;
|
||||
@@ -91,10 +91,10 @@ public:
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
void insert(const std::string& env_id, EnvChoice<_Tp> choice)
|
||||
template <typename Tp>
|
||||
void insert(const std::string& env_id, EnvChoice<Tp> choice)
|
||||
{
|
||||
_Tp& val = std::get<0>(choice);
|
||||
Tp& val = std::get<0>(choice);
|
||||
std::string& str_val = std::get<1>(choice);
|
||||
std::string& descript = std::get<2>(choice);
|
||||
|
||||
@@ -150,23 +150,23 @@ private:
|
||||
// GetEnv<int>("FORCENUMBEROFTHREADS",
|
||||
// std::thread::hardware_concurrency());
|
||||
//
|
||||
template <typename _Tp>
|
||||
_Tp
|
||||
GetEnv(const std::string& env_id, _Tp _default = _Tp())
|
||||
template <typename Tp>
|
||||
Tp
|
||||
GetEnv(const std::string& env_id, Tp _default = Tp())
|
||||
{
|
||||
char* env_var = std::getenv(env_id.c_str());
|
||||
if(env_var)
|
||||
{
|
||||
std::string str_var = std::string(env_var);
|
||||
std::istringstream iss(str_var);
|
||||
_Tp var = _Tp();
|
||||
Tp var = Tp();
|
||||
iss >> var;
|
||||
// record value defined by environment
|
||||
EnvSettings::GetInstance()->insert<_Tp>(env_id, var);
|
||||
EnvSettings::GetInstance()->insert<Tp>(env_id, var);
|
||||
return var;
|
||||
}
|
||||
// record default value
|
||||
EnvSettings::GetInstance()->insert<_Tp>(env_id, _default);
|
||||
EnvSettings::GetInstance()->insert<Tp>(env_id, _default);
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
@@ -207,25 +207,25 @@ GetEnv(const std::string& env_id, bool _default)
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// overload for GetEnv + message when set
|
||||
//
|
||||
template <typename _Tp>
|
||||
_Tp
|
||||
GetEnv(const std::string& env_id, _Tp _default, const std::string& msg)
|
||||
template <typename Tp>
|
||||
Tp
|
||||
GetEnv(const std::string& env_id, Tp _default, const std::string& msg)
|
||||
{
|
||||
char* env_var = std::getenv(env_id.c_str());
|
||||
if(env_var)
|
||||
{
|
||||
std::string str_var = std::string(env_var);
|
||||
std::istringstream iss(str_var);
|
||||
_Tp var = _Tp();
|
||||
Tp var = Tp();
|
||||
iss >> var;
|
||||
std::cout << "Environment variable \"" << env_id << "\" enabled with "
|
||||
<< "value == " << var << ". " << msg << std::endl;
|
||||
// record value defined by environment
|
||||
EnvSettings::GetInstance()->insert<_Tp>(env_id, var);
|
||||
EnvSettings::GetInstance()->insert<Tp>(env_id, var);
|
||||
return var;
|
||||
}
|
||||
// record default value
|
||||
EnvSettings::GetInstance()->insert<_Tp>(env_id, _default);
|
||||
EnvSettings::GetInstance()->insert<Tp>(env_id, _default);
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
@@ -241,9 +241,9 @@ GetEnv(const std::string& env_id, _Tp _default, const std::string& msg)
|
||||
//
|
||||
// int eInterp = GetEnv<int>("INTERPOLATION", choices, CUBIC);
|
||||
//
|
||||
template <typename _Tp>
|
||||
_Tp
|
||||
GetEnv(const std::string& env_id, const EnvChoiceList<_Tp>& _choices, _Tp _default)
|
||||
template <typename Tp>
|
||||
Tp
|
||||
GetEnv(const std::string& env_id, const EnvChoiceList<Tp>& _choices, Tp _default)
|
||||
{
|
||||
auto asupper = [](std::string var) {
|
||||
for(auto& itr : var)
|
||||
@@ -256,7 +256,7 @@ GetEnv(const std::string& env_id, const EnvChoiceList<_Tp>& _choices, _Tp _defau
|
||||
{
|
||||
std::string str_var = std::string(env_var);
|
||||
std::string upp_var = asupper(str_var);
|
||||
_Tp var = _Tp();
|
||||
Tp var = Tp();
|
||||
// check to see if string matches a choice
|
||||
for(const auto& itr : _choices)
|
||||
{
|
||||
@@ -302,7 +302,7 @@ GetEnv(const std::string& env_id, const EnvChoiceList<_Tp>& _choices, _Tp _defau
|
||||
}
|
||||
|
||||
// record default value
|
||||
EnvSettings::GetInstance()->insert(env_id, EnvChoice<_Tp>(_default, _name, _desc));
|
||||
EnvSettings::GetInstance()->insert(env_id, EnvChoice<Tp>(_default, _name, _desc));
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
@@ -310,9 +310,9 @@ GetEnv(const std::string& env_id, const EnvChoiceList<_Tp>& _choices, _Tp _defau
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename _Tp>
|
||||
_Tp
|
||||
GetChoice(const EnvChoiceList<_Tp>& _choices, const std::string str_var)
|
||||
template <typename Tp>
|
||||
Tp
|
||||
GetChoice(const EnvChoiceList<Tp>& _choices, const std::string str_var)
|
||||
{
|
||||
auto asupper = [](std::string var) {
|
||||
for(auto& itr : var)
|
||||
@@ -321,7 +321,7 @@ GetChoice(const EnvChoiceList<_Tp>& _choices, const std::string str_var)
|
||||
};
|
||||
|
||||
std::string upp_var = asupper(str_var);
|
||||
_Tp var = _Tp();
|
||||
Tp var = Tp();
|
||||
// check to see if string matches a choice
|
||||
for(const auto& itr : _choices)
|
||||
{
|
||||
|
||||
+4
-9
@@ -50,15 +50,13 @@ namespace PTL
|
||||
{
|
||||
class ThreadPool;
|
||||
|
||||
#define _MOVE_MEMBER(_member) _member = std::move(rhs._member)
|
||||
|
||||
class VTaskGroup
|
||||
{
|
||||
public:
|
||||
template <typename _Tp>
|
||||
using container_type = std::vector<_Tp>;
|
||||
template <typename _Tp>
|
||||
using list_type = std::vector<_Tp>;
|
||||
template <typename Tp>
|
||||
using container_type = std::vector<Tp>;
|
||||
template <typename Tp>
|
||||
using list_type = std::vector<Tp>;
|
||||
|
||||
typedef VTaskGroup this_type;
|
||||
typedef std::thread::id tid_type;
|
||||
@@ -154,7 +152,4 @@ VTaskGroup::clear()
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// don't pollute
|
||||
#undef _MOVE_MEMBER
|
||||
|
||||
} // namespace PTL
|
||||
|
||||
+24
-25
@@ -114,44 +114,43 @@ public:
|
||||
// virtual uintmax_t operator--(int) = 0;
|
||||
|
||||
public:
|
||||
template <typename _Container, size_t... Idx>
|
||||
static auto ContainerToTupleImpl(_Container&& container,
|
||||
details::index_sequence<Idx...>)
|
||||
-> decltype(std::make_tuple(std::forward<_Container>(container)[Idx]...))
|
||||
template <typename ContainerT, size_t... Idx>
|
||||
static auto ContainerToTupleImpl(ContainerT&& container, mpl::index_sequence<Idx...>)
|
||||
-> decltype(std::make_tuple(std::forward<ContainerT>(container)[Idx]...))
|
||||
{
|
||||
return std::make_tuple(std::forward<_Container>(container)[Idx]...);
|
||||
return std::make_tuple(std::forward<ContainerT>(container)[Idx]...);
|
||||
}
|
||||
|
||||
template <std::size_t _N, typename _Container>
|
||||
static auto ContainerToTuple(_Container&& container)
|
||||
-> decltype(ContainerToTupleImpl(std::forward<_Container>(container),
|
||||
details::make_index_sequence<_N>{}))
|
||||
template <std::size_t N, typename ContainerT>
|
||||
static auto ContainerToTuple(ContainerT&& container)
|
||||
-> decltype(ContainerToTupleImpl(std::forward<ContainerT>(container),
|
||||
mpl::make_index_sequence<N>{}))
|
||||
{
|
||||
return ContainerToTupleImpl(std::forward<_Container>(container),
|
||||
details::make_index_sequence<_N>{});
|
||||
return ContainerToTupleImpl(std::forward<ContainerT>(container),
|
||||
mpl::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
template <std::size_t _N, std::size_t _Nt, typename _Tuple,
|
||||
enable_if_t<(_N == _Nt), int> = 0>
|
||||
static void _Executor(_Tuple&& _t)
|
||||
template <std::size_t N, std::size_t Nt, typename TupleT,
|
||||
enable_if_t<(N == Nt), int> = 0>
|
||||
static void TExecutor(TupleT&& _t)
|
||||
{
|
||||
if(std::get<_N>(_t).get())
|
||||
(*(std::get<_N>(_t)))();
|
||||
if(std::get<N>(_t).get())
|
||||
(*(std::get<N>(_t)))();
|
||||
}
|
||||
|
||||
template <std::size_t _N, std::size_t _Nt, typename _Tuple,
|
||||
enable_if_t<(_N < _Nt), int> = 0>
|
||||
static void _Executor(_Tuple&& _t)
|
||||
template <std::size_t N, std::size_t Nt, typename TupleT,
|
||||
enable_if_t<(N < Nt), int> = 0>
|
||||
static void TExecutor(TupleT&& _t)
|
||||
{
|
||||
if(std::get<_N>(_t).get())
|
||||
(*(std::get<_N>(_t)))();
|
||||
_Executor<_N + 1, _Nt, _Tuple>(std::forward<_Tuple>(_t));
|
||||
if(std::get<N>(_t).get())
|
||||
(*(std::get<N>(_t)))();
|
||||
TExecutor<N + 1, Nt, TupleT>(std::forward<TupleT>(_t));
|
||||
}
|
||||
|
||||
template <typename _Tuple, std::size_t _N = std::tuple_size<decay_t<_Tuple>>::value>
|
||||
static void Executor(_Tuple&& __t)
|
||||
template <typename TupleT, std::size_t N = std::tuple_size<decay_t<TupleT>>::value>
|
||||
static void Executor(TupleT&& __t)
|
||||
{
|
||||
_Executor<0, _N - 1, _Tuple>(std::forward<_Tuple>(__t));
|
||||
TExecutor<0, N - 1, TupleT>(std::forward<TupleT>(__t));
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
|
||||
Reference in New Issue
Block a user