Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
PTL::TaskGroup< Tp, Arg, MaxDepth > Class Template Reference

#include <TaskGroup.hh>

Public Types

template<typename Up >
using container_type = std::vector<Up>
 
using tid_type = std::thread::id
 
using size_type = uintmax_t
 
using lock_t = Mutex
 
using atomic_int = std::atomic_intmax_t
 
using atomic_uint = std::atomic_uintmax_t
 
using condition_t = Condition
 
using ArgTp = decay_t<Arg>
 
using result_type = Tp
 
using task_pointer = std::shared_ptr<TaskFuture<ArgTp>>
 
using task_list_t = container_type<task_pointer>
 
using this_type = TaskGroup<Tp, Arg, MaxDepth>
 
using promise_type = std::promise<ArgTp>
 
using future_type = std::future<ArgTp>
 
using packaged_task_type = std::packaged_task<ArgTp()>
 
using future_list_t = container_type<future_type>
 
using join_type = typename JoinFunction<Tp, Arg>::Type
 
using iterator = typename future_list_t::iterator
 
using reverse_iterator = typename future_list_t::reverse_iterator
 
using const_iterator = typename future_list_t::const_iterator
 
using const_reverse_iterator = typename future_list_t::const_reverse_iterator
 
template<typename... Args>
using task_type = Task<ArgTp, decay_t<Args>...>
 

Public Member Functions

template<typename Func >
 TaskGroup (Func &&_join, ThreadPool *_tp=internal::get_default_threadpool())
 
template<typename Up = Tp>
 TaskGroup (ThreadPool *_tp=internal::get_default_threadpool(), enable_if_t< std::is_void< Up >::value, int >=0)
 
 ~TaskGroup ()
 
 TaskGroup (const this_type &)=delete
 
 TaskGroup (this_type &&rhs)=default
 
TaskGroupoperator= (const this_type &rhs)=delete
 
TaskGroupoperator= (this_type &&rhs)=default
 
template<typename Up >
std::shared_ptr< Up > operator+= (std::shared_ptr< Up > &&_task)
 
void wait ()
 
intmax_t operator++ ()
 
intmax_t operator++ (int)
 
intmax_t operator-- ()
 
intmax_t operator-- (int)
 
intmax_t size () const
 
lock_ttask_lock ()
 
condition_ttask_cond ()
 
uintmax_t id () const
 
void set_pool (ThreadPool *tp)
 
ThreadPool *& pool ()
 
ThreadPoolpool () const
 
bool is_native_task_group () const
 
bool is_main () const
 
intmax_t pending ()
 
ScopeDestructor get_scope_destructor ()
 
void notify ()
 
void notify_all ()
 
void reserve (size_t _n)
 
template<typename Func , typename... Args>
std::shared_ptr< task_type< Args... > > wrap (Func func, Args... args)
 
template<typename Func , typename... Args, typename Up = Tp>
enable_if_t< std::is_void< Up >::value, void > exec (Func func, Args... args)
 
template<typename Func , typename... Args, typename Up = Tp>
enable_if_t<!std::is_void< Up >::value, void > exec (Func func, Args... args)
 
template<typename Func , typename... Args>
void run (Func func, Args... args)
 
future_list_tget_tasks ()
 
const future_list_tget_tasks () const
 
itr_t begin ()
 
itr_t end ()
 
citr_t begin () const
 
citr_t end () const
 
citr_t cbegin () const
 
citr_t cend () const
 
ritr_t rbegin ()
 
ritr_t rend ()
 
critr_t rbegin () const
 
critr_t rend () const
 
template<typename Up = Tp, enable_if_t<!std::is_void< Up >::value, int > = 0>
Up join (Up accum={})
 
template<typename Up = Tp, typename Rp = Arg, enable_if_t< std::is_void< Up >::value &&std::is_void< Rp >::value, int > = 0>
void join ()
 
template<typename Up = Tp, typename Rp = Arg, enable_if_t< std::is_void< Up >::value &&!std::is_void< Rp >::value, int > = 0>
void join ()
 
void clear ()
 

Static Public Member Functions

static void set_verbose (int level)
 

Protected Types

using itr_t = iterator
 
using citr_t = const_iterator
 
using ritr_t = reverse_iterator
 
using critr_t = const_reverse_iterator
 

Protected Member Functions

template<typename Up , typename Func , typename... Args>
enable_if_t< std::is_void< Up >::value, void > local_exec (Func func, Args... args)
 
template<typename Up , typename Func , typename... Args>
enable_if_t<!std::is_void< Up >::value, void > local_exec (Func func, Args... args)
 
atomic_inttask_count ()
 
const atomic_inttask_count () const
 

Static Protected Member Functions

static tid_type this_tid ()
 

Protected Attributes

uintmax_t m_id = internal::task_group_counter()++
 
intmax_t m_depth = internal::get_task_depth()
 
tid_type m_main_tid = std::this_thread::get_id()
 
atomic_int m_tot_task_count { 0 }
 
lock_t m_task_lock = {}
 
condition_t m_task_cond = {}
 
join_type m_join {}
 
ThreadPoolm_pool = internal::get_default_threadpool()
 
tbb_task_group_tm_tbb_task_group = nullptr
 
task_list_t m_task_list = {}
 
future_list_t m_future_list = {}
 

Static Protected Attributes

static int f_verbose = GetEnv<int>("PTL_VERBOSE", 0)
 

Detailed Description

template<typename Tp, typename Arg = Tp, intmax_t MaxDepth = 0>
class PTL::TaskGroup< Tp, Arg, MaxDepth >

Definition at line 82 of file TaskGroup.hh.

Member Typedef Documentation

◆ ArgTp

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::ArgTp = decay_t<Arg>

Definition at line 95 of file TaskGroup.hh.

◆ atomic_int

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::atomic_int = std::atomic_intmax_t

Definition at line 92 of file TaskGroup.hh.

◆ atomic_uint

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::atomic_uint = std::atomic_uintmax_t

Definition at line 93 of file TaskGroup.hh.

◆ citr_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::citr_t = const_iterator
protected

Definition at line 213 of file TaskGroup.hh.

◆ condition_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::condition_t = Condition

Definition at line 94 of file TaskGroup.hh.

◆ const_iterator

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::const_iterator = typename future_list_t::const_iterator

Definition at line 107 of file TaskGroup.hh.

◆ const_reverse_iterator

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::const_reverse_iterator = typename future_list_t::const_reverse_iterator

Definition at line 108 of file TaskGroup.hh.

◆ container_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
template<typename Up >
using PTL::TaskGroup< Tp, Arg, MaxDepth >::container_type = std::vector<Up>

Definition at line 87 of file TaskGroup.hh.

◆ critr_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::critr_t = const_reverse_iterator
protected

Definition at line 215 of file TaskGroup.hh.

◆ future_list_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::future_list_t = container_type<future_type>

Definition at line 103 of file TaskGroup.hh.

◆ future_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::future_type = std::future<ArgTp>

Definition at line 101 of file TaskGroup.hh.

◆ iterator

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::iterator = typename future_list_t::iterator

Definition at line 105 of file TaskGroup.hh.

◆ itr_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::itr_t = iterator
protected

Definition at line 212 of file TaskGroup.hh.

◆ join_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::join_type = typename JoinFunction<Tp, Arg>::Type

Definition at line 104 of file TaskGroup.hh.

◆ lock_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::lock_t = Mutex

Definition at line 91 of file TaskGroup.hh.

◆ packaged_task_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::packaged_task_type = std::packaged_task<ArgTp()>

Definition at line 102 of file TaskGroup.hh.

◆ promise_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::promise_type = std::promise<ArgTp>

Definition at line 100 of file TaskGroup.hh.

◆ result_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::result_type = Tp

Definition at line 96 of file TaskGroup.hh.

◆ reverse_iterator

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::reverse_iterator = typename future_list_t::reverse_iterator

Definition at line 106 of file TaskGroup.hh.

◆ ritr_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::ritr_t = reverse_iterator
protected

Definition at line 214 of file TaskGroup.hh.

◆ size_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::size_type = uintmax_t

Definition at line 90 of file TaskGroup.hh.

◆ task_list_t

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::task_list_t = container_type<task_pointer>

Definition at line 98 of file TaskGroup.hh.

◆ task_pointer

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::task_pointer = std::shared_ptr<TaskFuture<ArgTp>>

Definition at line 97 of file TaskGroup.hh.

◆ task_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
template<typename... Args>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::task_type = Task<ArgTp, decay_t<Args>...>

Definition at line 111 of file TaskGroup.hh.

◆ this_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::this_type = TaskGroup<Tp, Arg, MaxDepth>

Definition at line 99 of file TaskGroup.hh.

◆ tid_type

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
using PTL::TaskGroup< Tp, Arg, MaxDepth >::tid_type = std::thread::id

Definition at line 89 of file TaskGroup.hh.

Constructor & Destructor Documentation

◆ TaskGroup() [1/4]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Func >
PTL::TaskGroup< Tp, Arg, MaxDepth >::TaskGroup ( Func && _join,
ThreadPool * _tp = internal::get_default_threadpool() )

Definition at line 290 of file TaskGroup.hh.

291: m_join{ std::forward<Func>(_join) }
292, m_pool{ _tp }
293{
294 internal_update();
295}
ThreadPool * m_pool
Definition TaskGroup.hh:276
join_type m_join
Definition TaskGroup.hh:275

◆ TaskGroup() [2/4]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up >
PTL::TaskGroup< Tp, Arg, MaxDepth >::TaskGroup ( ThreadPool * _tp = internal::get_default_threadpool(),
enable_if_t< std::is_void< Up >::value, int > = 0 )

Definition at line 299 of file TaskGroup.hh.

301: m_join{ []() {} }
302, m_pool{ _tp }
303{
304 internal_update();
305}

◆ ~TaskGroup()

template<typename Tp , typename Arg , intmax_t MaxDepth>
PTL::TaskGroup< Tp, Arg, MaxDepth >::~TaskGroup ( )

Definition at line 309 of file TaskGroup.hh.

310{
311 {
312 // task will decrement counter and then acquire the lock to notify
313 // condition variable so acquiring lock here will prevent the
314 // task group from being destroyed before this is completed
315 AutoLock _lk{ m_task_lock, std::defer_lock };
316 if(!_lk.owns_lock())
317 _lk.lock();
318 }
319
321 {
322 auto* _arena = m_pool->get_task_arena();
323 _arena->execute([this]() { this->m_tbb_task_group->wait(); });
324 }
325 delete m_tbb_task_group;
326 this->clear();
327}
tbb_task_group_t * m_tbb_task_group
Definition TaskGroup.hh:277
lock_t m_task_lock
Definition TaskGroup.hh:273
tbb_task_arena_t * get_task_arena()
auto execute(FuncT &&_func) -> decltype(_func())
TemplateAutoLock< Mutex > AutoLock
Definition AutoLock.hh:479

◆ TaskGroup() [3/4]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
PTL::TaskGroup< Tp, Arg, MaxDepth >::TaskGroup ( const this_type & )
delete

◆ TaskGroup() [4/4]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
PTL::TaskGroup< Tp, Arg, MaxDepth >::TaskGroup ( this_type && rhs)
default

Member Function Documentation

◆ begin() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
itr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::begin ( )
inline

Definition at line 227 of file TaskGroup.hh.

227{ return m_future_list.begin(); }
future_list_t m_future_list
Definition TaskGroup.hh:279

◆ begin() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
citr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::begin ( ) const
inline

Definition at line 229 of file TaskGroup.hh.

229{ return m_future_list.begin(); }

◆ cbegin()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
citr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::cbegin ( ) const
inline

Definition at line 231 of file TaskGroup.hh.

231{ return m_future_list.begin(); }

◆ cend()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
citr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::cend ( ) const
inline

Definition at line 232 of file TaskGroup.hh.

232{ return m_future_list.end(); }

◆ clear()

template<typename Tp , typename Arg , intmax_t MaxDepth>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::clear ( )

Definition at line 708 of file TaskGroup.hh.

709{
710 m_future_list.clear();
711 m_task_list.clear();
712}
task_list_t m_task_list
Definition TaskGroup.hh:278

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::clear().

◆ end() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
itr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::end ( )
inline

Definition at line 228 of file TaskGroup.hh.

228{ return m_future_list.end(); }

◆ end() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
citr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::end ( ) const
inline

Definition at line 230 of file TaskGroup.hh.

230{ return m_future_list.end(); }

◆ exec() [1/2]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Func , typename... Args, typename Up >
enable_if_t< std::is_void< Up >::value, void > PTL::TaskGroup< Tp, Arg, MaxDepth >::exec ( Func func,
Args... args )

Definition at line 531 of file TaskGroup.hh.

532{
533 if(MaxDepth > 0 && !m_tbb_task_group && ThreadData::GetInstance() &&
534 ThreadData::GetInstance()->task_depth > MaxDepth)
535 {
536 local_exec<Tp>(std::move(func), std::move(args)...);
537 }
538 else
539 {
540 auto& _counter = m_tot_task_count;
541 auto& _task_cond = task_cond();
542 auto& _task_lock = task_lock();
543 auto _task = wrap([&_task_cond, &_task_lock, &_counter, func, args...]() {
544 auto* _tdata = ThreadData::GetInstance();
545 if(_tdata)
546 ++(_tdata->task_depth);
547 func(args...);
548 auto _count = --(_counter);
549 if(_tdata)
550 --(_tdata->task_depth);
551 if(_count < 1)
552 {
553 AutoLock _lk{ _task_lock };
554 _task_cond.notify_all();
555 }
556 });
557
559 {
560 auto* _arena = m_pool->get_task_arena();
561 auto* _tbb_task_group = m_tbb_task_group;
562 auto* _ptask = _task.get();
563 _arena->execute([_tbb_task_group, _ptask]() {
564 _tbb_task_group->run([_ptask]() { (*_ptask)(); });
565 });
566 }
567 else
568 {
569 m_pool->add_task(std::move(_task));
570 }
571 }
572}
enable_if_t< std::is_void< Up >::value, void > local_exec(Func func, Args... args)
Definition TaskGroup.hh:623
atomic_int m_tot_task_count
Definition TaskGroup.hh:272
condition_t & task_cond()
Definition TaskGroup.hh:155
std::shared_ptr< task_type< Args... > > wrap(Func func, Args... args)
Definition TaskGroup.hh:186
lock_t & task_lock()
Definition TaskGroup.hh:154
static ThreadData *& GetInstance()
Definition ThreadData.cc:32
size_type add_task(task_pointer &&task, int bin=-1)

Referenced by G4TaskRunManager::AddEventTask(), PTL::TaskManager::exec(), PTL::TaskManager::exec(), PTL::TaskManager::rexec(), PTL::TaskManager::rexec(), PTL::TaskManager::rexec(), PTL::TaskManager::rexec(), and PTL::TaskGroup< Tp, Arg, MaxDepth >::run().

◆ exec() [2/2]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Func , typename... Args, typename Up >
enable_if_t<!std::is_void< Up >::value, void > PTL::TaskGroup< Tp, Arg, MaxDepth >::exec ( Func func,
Args... args )

Definition at line 576 of file TaskGroup.hh.

577{
578 if(MaxDepth > 0 && !m_tbb_task_group && ThreadData::GetInstance() &&
579 ThreadData::GetInstance()->task_depth > MaxDepth)
580 {
581 local_exec<Tp>(std::move(func), std::move(args)...);
582 }
583 else
584 {
585 auto& _counter = m_tot_task_count;
586 auto& _task_cond = task_cond();
587 auto& _task_lock = task_lock();
588 auto _task = wrap([&_task_cond, &_task_lock, &_counter, func, args...]() {
589 auto* _tdata = ThreadData::GetInstance();
590 if(_tdata)
591 ++(_tdata->task_depth);
592 auto&& _ret = func(args...);
593 auto _count = --(_counter);
594 if(_tdata)
595 --(_tdata->task_depth);
596 if(_count < 1)
597 {
598 AutoLock _lk{ _task_lock };
599 _task_cond.notify_all();
600 }
601 return std::forward<decltype(_ret)>(_ret);
602 });
603
605 {
606 auto* _arena = m_pool->get_task_arena();
607 auto* _tbb_task_group = m_tbb_task_group;
608 auto* _ptask = _task.get();
609 _arena->execute([_tbb_task_group, _ptask]() {
610 _tbb_task_group->run([_ptask]() { (*_ptask)(); });
611 });
612 }
613 else
614 {
615 m_pool->add_task(std::move(_task));
616 }
617 }
618}

◆ get_scope_destructor()

template<typename Tp , typename Arg , intmax_t MaxDepth>
ScopeDestructor PTL::TaskGroup< Tp, Arg, MaxDepth >::get_scope_destructor ( )

Definition at line 497 of file TaskGroup.hh.

498{
499 auto& _counter = m_tot_task_count;
500 auto& _task_cond = task_cond();
501 auto& _task_lock = task_lock();
502 return ScopeDestructor{ [&_task_cond, &_task_lock, &_counter]() {
503 auto _count = --(_counter);
504 if(_count < 1)
505 {
506 AutoLock _lk{ _task_lock };
507 _task_cond.notify_all();
508 }
509 } };
510}

◆ get_tasks() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
future_list_t & PTL::TaskGroup< Tp, Arg, MaxDepth >::get_tasks ( )
inline

Definition at line 221 of file TaskGroup.hh.

221{ return m_future_list; }

◆ get_tasks() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
const future_list_t & PTL::TaskGroup< Tp, Arg, MaxDepth >::get_tasks ( ) const
inline

Definition at line 222 of file TaskGroup.hh.

222{ return m_future_list; }

◆ id()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
uintmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::id ( ) const
inline

Definition at line 158 of file TaskGroup.hh.

158{ return m_id; }
uintmax_t m_id
Definition TaskGroup.hh:269

◆ is_main()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
bool PTL::TaskGroup< Tp, Arg, MaxDepth >::is_main ( ) const
inline

Definition at line 166 of file TaskGroup.hh.

166{ return this_tid() == m_main_tid; }
static tid_type this_tid()
Definition TaskGroup.hh:259
tid_type m_main_tid
Definition TaskGroup.hh:271

◆ is_native_task_group()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
bool PTL::TaskGroup< Tp, Arg, MaxDepth >::is_native_task_group ( ) const
inline

Definition at line 165 of file TaskGroup.hh.

165{ return (m_tbb_task_group) == nullptr; }

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::wrap().

◆ join() [1/3]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up , typename Rp , enable_if_t< std::is_void< Up >::value &&!std::is_void< Rp >::value, int > >
void PTL::TaskGroup< Tp, Arg, MaxDepth >::join ( )
inline

Definition at line 675 of file TaskGroup.hh.

676{
677 this->wait();
678 for(auto& itr : m_task_list)
679 itr->get();
680 for(auto& itr : m_future_list)
681 itr.get();
682 m_join();
683 this->clear();
684}

◆ join() [2/3]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
template<typename Up = Tp, typename Rp = Arg, enable_if_t< std::is_void< Up >::value &&!std::is_void< Rp >::value, int > = 0>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::join ( )
inline

◆ join() [3/3]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up , enable_if_t<!std::is_void< Up >::value, int > >
Up PTL::TaskGroup< Tp, Arg, MaxDepth >::join ( Up accum = {})
inline

Definition at line 654 of file TaskGroup.hh.

655{
656 this->wait();
657 for(auto& itr : m_task_list)
658 {
659 using RetT = decay_t<decltype(itr->get())>;
660 accum = std::move(m_join(std::ref(accum), std::forward<RetT>(itr->get())));
661 }
662 for(auto& itr : m_future_list)
663 {
664 using RetT = decay_t<decltype(itr.get())>;
665 accum = std::move(m_join(std::ref(accum), std::forward<RetT>(itr.get())));
666 }
667 this->clear();
668 return accum;
669}
typename std::decay< T >::type decay_t
Definition Globals.hh:54

Referenced by G4TaskRunManager::TerminateWorkers(), and G4TaskRunManager::WaitForEndEventLoopWorkers().

◆ local_exec() [1/2]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up , typename Func , typename... Args>
enable_if_t< std::is_void< Up >::value, void > PTL::TaskGroup< Tp, Arg, MaxDepth >::local_exec ( Func func,
Args... args )
protected

Definition at line 623 of file TaskGroup.hh.

624{
625 auto* _tdata = ThreadData::GetInstance();
626 if(_tdata)
627 ++(_tdata->task_depth);
628 promise_type _p{};
629 m_future_list.emplace_back(_p.get_future());
630 func(args...);
631 _p.set_value();
632 if(_tdata)
633 --(_tdata->task_depth);
634}
std::promise< ArgTp > promise_type
Definition TaskGroup.hh:100

◆ local_exec() [2/2]

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up , typename Func , typename... Args>
enable_if_t<!std::is_void< Up >::value, void > PTL::TaskGroup< Tp, Arg, MaxDepth >::local_exec ( Func func,
Args... args )
protected

Definition at line 639 of file TaskGroup.hh.

640{
641 auto* _tdata = ThreadData::GetInstance();
642 if(_tdata)
643 ++(_tdata->task_depth);
644 promise_type _p{};
645 m_future_list.emplace_back(_p.get_future());
646 _p.set_value(func(args...));
647 if(_tdata)
648 --(_tdata->task_depth);
649}

◆ notify()

template<typename Tp , typename Arg , intmax_t MaxDepth>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::notify ( )

Definition at line 514 of file TaskGroup.hh.

515{
516 AutoLock _lk{ m_task_lock };
517 m_task_cond.notify_one();
518}
condition_t m_task_cond
Definition TaskGroup.hh:274

◆ notify_all()

template<typename Tp , typename Arg , intmax_t MaxDepth>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::notify_all ( )

Definition at line 522 of file TaskGroup.hh.

523{
524 AutoLock _lk{ m_task_lock };
525 m_task_cond.notify_all();
526}

◆ operator++() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::operator++ ( )
inline

Definition at line 145 of file TaskGroup.hh.

145{ return ++(m_tot_task_count); }

◆ operator++() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::operator++ ( int )
inline

Definition at line 146 of file TaskGroup.hh.

146{ return (m_tot_task_count)++; }

◆ operator+=()

template<typename Tp , typename Arg , intmax_t MaxDepth>
template<typename Up >
std::shared_ptr< Up > PTL::TaskGroup< Tp, Arg, MaxDepth >::operator+= ( std::shared_ptr< Up > && _task)

Definition at line 332 of file TaskGroup.hh.

333{
334 // thread-safe increment of tasks in task group
335 operator++();
336 // copy the shared pointer to abstract instance
337 m_task_list.push_back(_task);
338 // return the derived instance
339 return std::move(_task);
340}
intmax_t operator++()
Definition TaskGroup.hh:145

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::wrap().

◆ operator--() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::operator-- ( )
inline

Definition at line 147 of file TaskGroup.hh.

147{ return --(m_tot_task_count); }

◆ operator--() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::operator-- ( int )
inline

Definition at line 148 of file TaskGroup.hh.

148{ return (m_tot_task_count)--; }

◆ operator=() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
TaskGroup & PTL::TaskGroup< Tp, Arg, MaxDepth >::operator= ( const this_type & rhs)
delete

◆ operator=() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
TaskGroup & PTL::TaskGroup< Tp, Arg, MaxDepth >::operator= ( this_type && rhs)
default

◆ pending()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::pending ( )
inline

Definition at line 169 of file TaskGroup.hh.

169{ return m_tot_task_count.load(); }

◆ pool() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
ThreadPool *& PTL::TaskGroup< Tp, Arg, MaxDepth >::pool ( )
inline

Definition at line 162 of file TaskGroup.hh.

162{ return m_pool; }

◆ pool() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
ThreadPool * PTL::TaskGroup< Tp, Arg, MaxDepth >::pool ( ) const
inline

Definition at line 163 of file TaskGroup.hh.

163{ return m_pool; }

◆ rbegin() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
ritr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::rbegin ( )
inline

Definition at line 233 of file TaskGroup.hh.

233{ return m_future_list.rbegin(); }

◆ rbegin() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
critr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::rbegin ( ) const
inline

Definition at line 235 of file TaskGroup.hh.

235{ return m_future_list.rbegin(); }

◆ rend() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
ritr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::rend ( )
inline

Definition at line 234 of file TaskGroup.hh.

234{ return m_future_list.rend(); }

◆ rend() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
critr_t PTL::TaskGroup< Tp, Arg, MaxDepth >::rend ( ) const
inline

Definition at line 236 of file TaskGroup.hh.

236{ return m_future_list.rend(); }

◆ reserve()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::reserve ( size_t _n)
inline

Definition at line 178 of file TaskGroup.hh.

179 {
180 m_task_list.reserve(_n);
181 m_future_list.reserve(_n);
182 }

◆ run()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
template<typename Func , typename... Args>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::run ( Func func,
Args... args )
inline

Definition at line 199 of file TaskGroup.hh.

200 {
201 exec(std::move(func), std::move(args)...);
202 }
enable_if_t< std::is_void< Up >::value, void > exec(Func func, Args... args)
Definition TaskGroup.hh:531

◆ set_pool()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::set_pool ( ThreadPool * tp)
inline

Definition at line 161 of file TaskGroup.hh.

◆ set_verbose()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
static void PTL::TaskGroup< Tp, Arg, MaxDepth >::set_verbose ( int level)
inlinestatic

Definition at line 171 of file TaskGroup.hh.

171{ f_verbose = level; }
static int f_verbose
Definition TaskGroup.hh:267

◆ size()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::size ( ) const
inline

Definition at line 151 of file TaskGroup.hh.

151{ return m_tot_task_count.load(); }

◆ task_cond()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
condition_t & PTL::TaskGroup< Tp, Arg, MaxDepth >::task_cond ( )
inline

Definition at line 155 of file TaskGroup.hh.

155{ return m_task_cond; }

◆ task_count() [1/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
atomic_int & PTL::TaskGroup< Tp, Arg, MaxDepth >::task_count ( )
inlineprotected

Definition at line 263 of file TaskGroup.hh.

263{ return m_tot_task_count; }

◆ task_count() [2/2]

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
const atomic_int & PTL::TaskGroup< Tp, Arg, MaxDepth >::task_count ( ) const
inlineprotected

Definition at line 264 of file TaskGroup.hh.

264{ return m_tot_task_count; }

◆ task_lock()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
lock_t & PTL::TaskGroup< Tp, Arg, MaxDepth >::task_lock ( )
inline

Definition at line 154 of file TaskGroup.hh.

154{ return m_task_lock; }

◆ this_tid()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
static tid_type PTL::TaskGroup< Tp, Arg, MaxDepth >::this_tid ( )
inlinestaticprotected

Definition at line 259 of file TaskGroup.hh.

259{ return std::this_thread::get_id(); }

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::is_main().

◆ wait()

template<typename Tp , typename Arg , intmax_t MaxDepth>
void PTL::TaskGroup< Tp, Arg, MaxDepth >::wait ( )

Definition at line 344 of file TaskGroup.hh.

345{
346 auto _dtor = ScopeDestructor{ [&]() {
348 {
349 auto* _arena = m_pool->get_task_arena();
350 _arena->execute([this]() { this->m_tbb_task_group->wait(); });
351 }
352 } };
353
354 ThreadData* data = ThreadData::GetInstance();
355 if(!data)
356 return;
357
358 // if no pool was initially present at creation
359 if(!m_pool)
360 {
361 // check for master MT run-manager
363
364 // if no thread pool created
365 if(!m_pool)
366 {
367 if(f_verbose > 0)
368 {
369 fprintf(stderr, "%s @ %i :: Warning! nullptr to thread-pool (%p)\n",
370 __FUNCTION__, __LINE__, static_cast<void*>(m_pool));
371 std::cerr << __FUNCTION__ << "@" << __LINE__ << " :: Warning! "
372 << "nullptr to thread pool!" << std::endl;
373 }
374 return;
375 }
376 }
377
378 ThreadPool* tpool = (m_pool) ? m_pool : data->thread_pool;
379 VUserTaskQueue* taskq = (tpool) ? tpool->get_queue() : data->current_queue;
380
381 bool _is_main = data->is_main;
382 bool _within_task = data->within_task;
383
384 auto is_active_state = [&]() {
385 return (tpool->state()->load(std::memory_order_relaxed) !=
386 thread_pool::state::STOPPED);
387 };
388
389 auto execute_this_threads_tasks = [&]() {
390 if(!taskq)
391 return;
392
393 // only want to process if within a task
394 if((!_is_main || tpool->size() < 2) && _within_task)
395 {
396 int bin = static_cast<int>(taskq->GetThreadBin());
397 // const auto nitr = (tpool) ? tpool->size() :
398 // Thread::hardware_concurrency();
399 while(this->pending() > 0)
400 {
401 if(!taskq->empty())
402 {
403 auto _task = taskq->GetTask(bin);
404 if(_task)
405 (*_task)();
406 }
407 }
408 }
409 };
410
411 // checks for validity
413 {
414 // for external threads
415 if(!_is_main || tpool->size() < 2)
416 return;
417 }
418 else if(f_verbose > 0)
419 {
420 if(!tpool || !taskq)
421 {
422 // something is wrong, didn't create thread-pool?
423 fprintf(stderr,
424 "%s @ %i :: Warning! nullptr to thread data (%p) or task-queue "
425 "(%p)\n",
426 __FUNCTION__, __LINE__, static_cast<void*>(tpool),
427 static_cast<void*>(taskq));
428 }
429 // return if thread pool isn't built
430 else if(is_native_task_group() && !tpool->is_alive())
431 {
432 fprintf(stderr, "%s @ %i :: Warning! thread-pool is not alive!\n",
433 __FUNCTION__, __LINE__);
434 }
435 else if(!is_active_state())
436 {
437 fprintf(stderr, "%s @ %i :: Warning! thread-pool is not active!\n",
438 __FUNCTION__, __LINE__);
439 }
440 }
441
442 intmax_t wake_size = 2;
443 AutoLock _lock(m_task_lock, std::defer_lock);
444
445 while(is_active_state())
446 {
447 execute_this_threads_tasks();
448
449 // while loop protects against spurious wake-ups
450 while(_is_main && pending() > 0 && is_active_state())
451 {
452 // auto _wake = [&]() { return (wake_size > pending() ||
453 // !is_active_state());
454 // };
455
456 // lock before sleeping on condition
457 if(!_lock.owns_lock())
458 _lock.lock();
459
460 // Wait until signaled that a task has been competed
461 // Unlock mutex while wait, then lock it back when signaled
462 // when true, this wakes the thread
463 if(pending() >= wake_size)
464 {
465 m_task_cond.wait(_lock);
466 }
467 else
468 {
469 m_task_cond.wait_for(_lock, std::chrono::microseconds(100));
470 }
471 // unlock
472 if(_lock.owns_lock())
473 _lock.unlock();
474 }
475
476 // if pending is not greater than zero, we are joined
477 if(pending() <= 0)
478 break;
479 }
480
481 if(_lock.owns_lock())
482 _lock.unlock();
483
484 intmax_t ntask = this->task_count().load();
485 if(ntask > 0)
486 {
487 std::stringstream ss;
488 ss << "\nWarning! Join operation issue! " << ntask << " tasks still "
489 << "are running!" << std::endl;
490 std::cerr << ss.str();
491 this->wait();
492 }
493}
bool is_native_task_group() const
Definition TaskGroup.hh:165
atomic_int & task_count()
Definition TaskGroup.hh:263
intmax_t pending()
Definition TaskGroup.hh:169
ThreadPool * get_default_threadpool()
Definition TaskGroup.cc:51

Referenced by G4TaskRunManager::CreateAndStartWorkers().

◆ wrap()

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
template<typename Func , typename... Args>
std::shared_ptr< task_type< Args... > > PTL::TaskGroup< Tp, Arg, MaxDepth >::wrap ( Func func,
Args... args )
inline

Definition at line 186 of file TaskGroup.hh.

187 {
188 return operator+=(std::make_shared<task_type<Args...>>(
189 is_native_task_group(), m_depth, std::move(func), std::move(args)...));
190 }
Task< ArgTp, decay_t< Args >... > task_type
Definition TaskGroup.hh:111
intmax_t m_depth
Definition TaskGroup.hh:270
std::shared_ptr< Up > operator+=(std::shared_ptr< Up > &&_task)
Definition TaskGroup.hh:332

Referenced by PTL::TaskManager::wrap(), and PTL::TaskManager::wrap().

Member Data Documentation

◆ f_verbose

template<typename Tp , typename Arg , intmax_t MaxDepth>
int PTL::TaskGroup< Tp, Arg, MaxDepth >::f_verbose = GetEnv<int>("PTL_VERBOSE", 0)
staticprotected

Definition at line 267 of file TaskGroup.hh.

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::set_verbose().

◆ m_depth

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
intmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::m_depth = internal::get_task_depth()
protected

Definition at line 270 of file TaskGroup.hh.

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::wrap().

◆ m_future_list

◆ m_id

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
uintmax_t PTL::TaskGroup< Tp, Arg, MaxDepth >::m_id = internal::task_group_counter()++
protected

Definition at line 269 of file TaskGroup.hh.

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::id().

◆ m_join

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
join_type PTL::TaskGroup< Tp, Arg, MaxDepth >::m_join {}
protected

Definition at line 275 of file TaskGroup.hh.

275{};

◆ m_main_tid

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
tid_type PTL::TaskGroup< Tp, Arg, MaxDepth >::m_main_tid = std::this_thread::get_id()
protected

Definition at line 271 of file TaskGroup.hh.

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::is_main().

◆ m_pool

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
ThreadPool* PTL::TaskGroup< Tp, Arg, MaxDepth >::m_pool = internal::get_default_threadpool()
protected

◆ m_task_cond

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
condition_t PTL::TaskGroup< Tp, Arg, MaxDepth >::m_task_cond = {}
protected

Definition at line 274 of file TaskGroup.hh.

274{};

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::task_cond().

◆ m_task_list

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
task_list_t PTL::TaskGroup< Tp, Arg, MaxDepth >::m_task_list = {}
protected

Definition at line 278 of file TaskGroup.hh.

278{};

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::reserve().

◆ m_task_lock

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
lock_t PTL::TaskGroup< Tp, Arg, MaxDepth >::m_task_lock = {}
protected

Definition at line 273 of file TaskGroup.hh.

273{};

Referenced by PTL::TaskGroup< Tp, Arg, MaxDepth >::task_lock().

◆ m_tbb_task_group

template<typename Tp , typename Arg = Tp, intmax_t MaxDepth = 0>
tbb_task_group_t* PTL::TaskGroup< Tp, Arg, MaxDepth >::m_tbb_task_group = nullptr
protected

◆ m_tot_task_count


The documentation for this class was generated from the following file: