Geant4-11
TaskManager.hh
Go to the documentation of this file.
1//
2// MIT License
3// Copyright (c) 2020 Jonathan R. Madsen
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
12// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
13// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
16// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
17// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18//
19// ---------------------------------------------------------------
20// Tasking class header file
21//
22// Class Description:
23//
24// This file creates a class for handling the wrapping of functions
25// into task objects and submitting to thread pool
26//
27// ---------------------------------------------------------------
28// Author: Jonathan Madsen (Feb 13th 2018)
29// ---------------------------------------------------------------
30
31#pragma once
32
33#include "PTL/Globals.hh"
34#include "PTL/TBBTaskGroup.hh"
35#include "PTL/Task.hh"
36#include "PTL/TaskGroup.hh"
37#include "PTL/ThreadPool.hh"
38#include "PTL/Threading.hh"
39
40#include <algorithm>
41#include <cassert>
42#include <cmath>
43#include <cstdint>
44#include <iomanip>
45
46namespace PTL
47{
48//======================================================================================//
49
51{
52public:
55
56public:
57 // Constructor and Destructors
58 explicit TaskManager(ThreadPool*);
59 virtual ~TaskManager();
60
61 TaskManager(const this_type&) = delete;
62 TaskManager(this_type&&) = default;
63 this_type& operator=(const this_type&) = delete;
65
66public:
68 static TaskManager* GetInstance();
70 static unsigned ncores() { return std::thread::hardware_concurrency(); }
71
72public:
73 //------------------------------------------------------------------------//
74 // return the thread pool
75 inline ThreadPool* thread_pool() const { return m_pool; }
76
77 //------------------------------------------------------------------------//
78 // return the number of threads in the thread pool
79 inline size_type size() const { return m_pool->size(); }
80
81 //------------------------------------------------------------------------//
82 // kill all the threads
83 inline void finalize() { m_pool->destroy_threadpool(); }
84 //------------------------------------------------------------------------//
85
86public:
87 //------------------------------------------------------------------------//
88 // direct insertion of a task
89 //------------------------------------------------------------------------//
90 template <typename... Args>
91 void exec(Task<Args...>* _task)
92 {
93 m_pool->add_task(_task);
94 }
95
96 //------------------------------------------------------------------------//
97 // direct insertion of a packaged_task
98 //------------------------------------------------------------------------//
99 template <typename RetT, typename FuncT, typename... Args>
100 std::shared_ptr<PackagedTask<RetT, Args...>> async(FuncT&& func, Args&&... args)
101 {
102 typedef PackagedTask<RetT, Args...> task_type;
103
104 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func),
105 std::forward<Args>(args)...);
106 m_pool->add_task(_ptask);
107 return _ptask;
108 }
109 //------------------------------------------------------------------------//
110 template <typename RetT, typename FuncT>
111 std::shared_ptr<PackagedTask<RetT>> async(FuncT&& func)
112 {
113 typedef PackagedTask<RetT> task_type;
114
115 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func));
116 m_pool->add_task(_ptask);
117 return _ptask;
118 }
119 //------------------------------------------------------------------------//
120 template <typename FuncT, typename... Args>
121 auto async(FuncT&& func, Args... args)
122 -> std::shared_ptr<PackagedTask<decay_t<decltype(func(args...))>, Args...>>
123 {
124 using RetT = decay_t<decltype(func(args...))>;
125 typedef PackagedTask<RetT, Args...> task_type;
126
127 auto _ptask = std::make_shared<task_type>(std::forward<FuncT>(func),
128 std::forward<Args>(args)...);
129 m_pool->add_task(_ptask);
130 return _ptask;
131 }
132 //------------------------------------------------------------------------//
133
134public:
135 //------------------------------------------------------------------------//
136 // public wrap functions
137 //------------------------------------------------------------------------//
138 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
140 FuncT&& func, Args&&... args)
141 {
142 return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
143 }
144 //------------------------------------------------------------------------//
145 template <typename RetT, typename ArgT, typename FuncT>
146 std::shared_ptr<Task<RetT, ArgT>> wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
147 {
148 return tg.wrap(std::forward<FuncT>(func));
149 }
150
151public:
152 //------------------------------------------------------------------------//
153 // public exec functions
154 //------------------------------------------------------------------------//
155 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
156 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
157 {
158 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
159 }
160 //------------------------------------------------------------------------//
161 template <typename RetT, typename ArgT, typename FuncT>
162 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
163 {
164 tg.exec(std::forward<FuncT>(func));
165 }
166 //------------------------------------------------------------------------//
167 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
168 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
169 {
170 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
171 }
172 //------------------------------------------------------------------------//
173 template <typename RetT, typename ArgT, typename FuncT>
174 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
175 {
176 tg.exec(std::forward<FuncT>(func));
177 }
178 //------------------------------------------------------------------------//
179 // public exec functions (void specializations)
180 //------------------------------------------------------------------------//
181 template <typename FuncT, typename... Args>
182 void rexec(TaskGroup<void, void>& tg, FuncT&& func, Args&&... args)
183 {
184 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
185 }
186 //------------------------------------------------------------------------//
187 template <typename FuncT>
188 void rexec(TaskGroup<void, void>& tg, FuncT&& func)
189 {
190 tg.exec(std::forward<FuncT>(func));
191 }
192 //------------------------------------------------------------------------//
193
194protected:
195 // Protected variables
196 ThreadPool* m_pool = nullptr;
197
198private:
199 static TaskManager*& fgInstance();
200};
201
202} // namespace PTL
203//======================================================================================//
204
205#include "TaskRunManager.hh"
206
207//--------------------------------------------------------------------------------------//
208
209inline PTL::TaskManager*&
211{
212 static thread_local TaskManager* _instance = nullptr;
213 return _instance;
214}
215
216//--------------------------------------------------------------------------------------//
217
218inline PTL::TaskManager*
220{
221 if(!fgInstance())
222 {
223 auto nthreads = std::thread::hardware_concurrency();
224 std::cout << "Allocating mad::TaskManager with " << nthreads << " thread(s)..."
225 << std::endl;
226 new TaskManager(TaskRunManager::GetMasterRunManager()->GetThreadPool());
227 }
228 return fgInstance();
229}
230
231//--------------------------------------------------------------------------------------//
232
233inline PTL::TaskManager*
235{
236 return fgInstance();
237}
238
239//--------------------------------------------------------------------------------------//
240
242: m_pool(_pool)
243{
244 if(!fgInstance())
245 fgInstance() = this;
246}
247
248//--------------------------------------------------------------------------------------//
249
251{
252 finalize();
253 if(fgInstance() == this)
254 fgInstance() = nullptr;
255}
256
257//======================================================================================//
static char ** args
Definition: G4Xt.cc:51
The task class is supplied to thread_pool.
Definition: Task.hh:82
std::shared_ptr< task_type< Args... > > wrap(Func func, Args... args)
Definition: TaskGroup.hh:167
enable_if_t< std::is_void< Up >::value, void > exec(Func func, Args... args)
ThreadPool::size_type size_type
Definition: TaskManager.hh:54
ThreadPool * thread_pool() const
Definition: TaskManager.hh:75
std::shared_ptr< PackagedTask< RetT > > async(FuncT &&func)
Definition: TaskManager.hh:111
TaskManager(this_type &&)=default
void rexec(TaskGroup< void, void > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:182
void rexec(TaskGroup< void, void > &tg, FuncT &&func)
Definition: TaskManager.hh:188
void exec(Task< Args... > *_task)
Definition: TaskManager.hh:91
TaskManager(ThreadPool *)
Definition: TaskManager.hh:241
static TaskManager *& fgInstance()
Definition: TaskManager.hh:210
this_type & operator=(const this_type &)=delete
void rexec(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:174
static TaskManager * GetInstanceIfExists()
Definition: TaskManager.hh:234
static TaskManager * GetInstance()
get the singleton pointer
Definition: TaskManager.hh:219
static unsigned ncores()
Definition: TaskManager.hh:70
this_type & operator=(this_type &&)=default
std::shared_ptr< Task< RetT, ArgT > > wrap(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:146
ThreadPool * m_pool
Definition: TaskManager.hh:196
virtual ~TaskManager()
Definition: TaskManager.hh:250
void rexec(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:168
size_type size() const
Definition: TaskManager.hh:79
std::shared_ptr< Task< RetT, ArgT, Args... > > wrap(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:139
void exec(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:156
void exec(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:162
TaskManager(const this_type &)=delete
TaskManager this_type
Definition: TaskManager.hh:53
auto async(FuncT &&func, Args... args) -> std::shared_ptr< PackagedTask< decay_t< decltype(func(args...))>, Args... > >
Definition: TaskManager.hh:121
std::shared_ptr< PackagedTask< RetT, Args... > > async(FuncT &&func, Args &&... args)
Definition: TaskManager.hh:100
static TaskRunManager * GetMasterRunManager(bool useTBB=false)
The task class is supplied to thread_pool.
Definition: Task.hh:132
size_type add_task(task_pointer &&task, int bin=-1)
Definition: ThreadPool.hh:380
size_t size_type
Definition: ThreadPool.hh:75
size_type size() const
Definition: ThreadPool.hh:163
size_type destroy_threadpool()
Definition: ThreadPool.cc:364
std::shared_ptr< T > shared_ptr
Definition: memory.h:15
Definition: AutoLock.hh:254
typename std::decay< T >::type decay_t
Definition: Globals.hh:68