Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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:
67 /// get the singleton pointer
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::future<RetT> async(FuncT&& func, Args&&... args)
101 {
102 typedef PackagedTask<RetT, Args...> task_type;
103 typedef task_type* task_pointer;
104
105 task_pointer _ptask =
106 new task_type(std::forward<FuncT>(func), std::forward<Args>(args)...);
107 std::future<RetT> _f = _ptask->get_future();
108 m_pool->add_task(_ptask);
109 return _f;
110 }
111 //------------------------------------------------------------------------//
112 template <typename RetT, typename FuncT>
113 std::future<RetT> async(FuncT&& func)
114 {
115 typedef PackagedTask<RetT> task_type;
116 typedef task_type* task_pointer;
117
118 task_pointer _ptask = new task_type(std::forward<FuncT>(func));
119 std::future<RetT> _f = _ptask->get_future();
120 m_pool->add_task(_ptask);
121 return _f;
122 }
123 //------------------------------------------------------------------------//
124 template <typename FuncT, typename... Args>
125 auto async(FuncT&& func, Args... args)
126 -> std::future<decay_t<decltype(func(args...))>>
127 {
128 using RetT = decay_t<decltype(func(args...))>;
129 typedef PackagedTask<RetT, Args...> task_type;
130
131 auto _ptask =
132 new task_type(std::forward<FuncT>(func), std::forward<Args>(args)...);
133 auto _f = _ptask->get_future();
134 m_pool->add_task(_ptask);
135 return _f;
136 }
137 //------------------------------------------------------------------------//
138
139public:
140 //------------------------------------------------------------------------//
141 // public wrap functions
142 //------------------------------------------------------------------------//
143 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
144 Task<RetT, ArgT, Args...>* wrap(TaskGroup<RetT, ArgT>& tg, FuncT&& func,
145 Args&&... args)
146 {
147 return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
148 }
149 //------------------------------------------------------------------------//
150 template <typename RetT, typename ArgT, typename FuncT>
152 {
153 return tg.wrap(std::forward<FuncT>(func));
154 }
155
156public:
157 //------------------------------------------------------------------------//
158 // public exec functions
159 //------------------------------------------------------------------------//
160 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
161 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
162 {
163 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
164 }
165 //------------------------------------------------------------------------//
166 template <typename RetT, typename ArgT, typename FuncT>
167 void exec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
168 {
169 tg.exec(std::forward<FuncT>(func));
170 }
171 //------------------------------------------------------------------------//
172 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
173 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
174 {
175 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
176 }
177 //------------------------------------------------------------------------//
178 template <typename RetT, typename ArgT, typename FuncT>
179 void rexec(TaskGroup<RetT, ArgT>& tg, FuncT&& func)
180 {
181 tg.exec(std::forward<FuncT>(func));
182 }
183 //------------------------------------------------------------------------//
184 // public exec functions (void specializations)
185 //------------------------------------------------------------------------//
186 template <typename FuncT, typename... Args>
187 void rexec(TaskGroup<void, void>& tg, FuncT&& func, Args&&... args)
188 {
189 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
190 }
191 //------------------------------------------------------------------------//
192 template <typename FuncT>
193 void rexec(TaskGroup<void, void>& tg, FuncT&& func)
194 {
195 tg.exec(std::forward<FuncT>(func));
196 }
197 //------------------------------------------------------------------------//
198
199#if defined(PTL_USE_TBB)
200 //------------------------------------------------------------------------//
201 // public wrap functions using TBB tasks
202 //------------------------------------------------------------------------//
203 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
204 Task<RetT, ArgT, Args...>* wrap(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func,
205 Args&&... args)
206 {
207 return tg.wrap(std::forward<FuncT>(func), std::forward<Args>(args)...);
208 }
209 //------------------------------------------------------------------------//
210 template <typename RetT, typename ArgT, typename FuncT>
211 Task<RetT, ArgT>* wrap(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func)
212 {
213 return tg.wrap(std::forward<FuncT>(func));
214 }
215
216 //------------------------------------------------------------------------//
217 // public exec functions using TBB tasks
218 //------------------------------------------------------------------------//
219 template <typename RetT, typename ArgT, typename FuncT, typename... Args>
220 void exec(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func, Args&&... args)
221 {
222 tg.exec(std::forward<FuncT>(func), std::forward<Args>(args)...);
223 }
224 //------------------------------------------------------------------------//
225 template <typename RetT, typename ArgT, typename FuncT>
226 void exec(TBBTaskGroup<RetT, ArgT>& tg, FuncT&& func)
227 {
228 tg.exec(std::forward<FuncT>(func));
229 }
230 //------------------------------------------------------------------------//
231#endif
232
233protected:
234 // Protected variables
235 ThreadPool* m_pool = nullptr;
236
237private:
238 static TaskManager*& fgInstance();
239};
240
241} // namespace PTL
242//======================================================================================//
243
244#include "TaskRunManager.hh"
245
246//--------------------------------------------------------------------------------------//
247
248inline PTL::TaskManager*&
249PTL::TaskManager::fgInstance()
250{
251 static thread_local TaskManager* _instance = nullptr;
252 return _instance;
253}
254
255//--------------------------------------------------------------------------------------//
256
257inline PTL::TaskManager*
259{
260 if(!fgInstance())
261 {
262 auto nthreads = std::thread::hardware_concurrency();
263 std::cout << "Allocating mad::TaskManager with " << nthreads << " thread(s)..."
264 << std::endl;
265 new TaskManager(TaskRunManager::GetMasterRunManager()->GetThreadPool());
266 }
267 return fgInstance();
268}
269
270//--------------------------------------------------------------------------------------//
271
272inline PTL::TaskManager*
274{
275 return fgInstance();
276}
277
278//--------------------------------------------------------------------------------------//
279
281: m_pool(_pool)
282{
283 if(!fgInstance())
284 fgInstance() = this;
285}
286
287//--------------------------------------------------------------------------------------//
288
290{
291 finalize();
292 if(fgInstance() == this)
293 fgInstance() = nullptr;
294}
295
296//======================================================================================//
The task class is supplied to thread_pool.
Definition: Task.hh:51
task_type< Args... > * wrap(Func &&func, Args... args)
Definition: TaskGroup.hh:206
void exec(Func &&func, Args... args)
Definition: TaskGroup.hh:215
ThreadPool::size_type size_type
Definition: TaskManager.hh:54
ThreadPool * thread_pool() const
Definition: TaskManager.hh:75
TaskManager(this_type &&)=default
void rexec(TaskGroup< void, void > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:187
void rexec(TaskGroup< void, void > &tg, FuncT &&func)
Definition: TaskManager.hh:193
void exec(Task< Args... > *_task)
Definition: TaskManager.hh:91
TaskManager(ThreadPool *)
Definition: TaskManager.hh:280
Task< RetT, ArgT, Args... > * wrap(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:144
this_type & operator=(const this_type &)=delete
void rexec(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:179
static TaskManager * GetInstanceIfExists()
Definition: TaskManager.hh:273
static TaskManager * GetInstance()
get the singleton pointer
Definition: TaskManager.hh:258
static unsigned ncores()
Definition: TaskManager.hh:70
this_type & operator=(this_type &&)=default
ThreadPool * m_pool
Definition: TaskManager.hh:235
Task< RetT, ArgT > * wrap(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:151
virtual ~TaskManager()
Definition: TaskManager.hh:289
void rexec(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:173
auto async(FuncT &&func, Args... args) -> std::future< decay_t< decltype(func(args...))> >
Definition: TaskManager.hh:125
size_type size() const
Definition: TaskManager.hh:79
std::future< RetT > async(FuncT &&func, Args &&... args)
Definition: TaskManager.hh:100
void exec(TaskGroup< RetT, ArgT > &tg, FuncT &&func, Args &&... args)
Definition: TaskManager.hh:161
void exec(TaskGroup< RetT, ArgT > &tg, FuncT &&func)
Definition: TaskManager.hh:167
std::future< RetT > async(FuncT &&func)
Definition: TaskManager.hh:113
TaskManager(const this_type &)=delete
TaskManager this_type
Definition: TaskManager.hh:53
static TaskRunManager * GetMasterRunManager(bool useTBB=false)
The task class is supplied to thread_pool.
Definition: Task.hh:104
size_type add_task(task_pointer task, int bin=-1)
Definition: ThreadPool.hh:328
size_t size_type
Definition: ThreadPool.hh:70
size_type size() const
Definition: ThreadPool.hh:151
size_type destroy_threadpool()
Definition: ThreadPool.cc:366
Definition: AutoLock.hh:254
typename std::decay< T >::type decay_t
Definition: Globals.hh:52