Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TaskGroup.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// ---------------------------------------------------------------
21// Tasking class header file
22//
23// Class Description:
24//
25// This file creates the a class for handling a group of tasks that
26// can be independently joined
27//
28// ---------------------------------------------------------------
29// Author: Jonathan Madsen (Feb 13th 2018)
30// ---------------------------------------------------------------
31
32#pragma once
33
34#include "PTL/Task.hh"
35#include "PTL/ThreadPool.hh"
36#include "PTL/VTaskGroup.hh"
37
38#include <cstdint>
39#include <deque>
40#include <future>
41#include <list>
42#include <vector>
43
44#ifdef PTL_USE_TBB
45# include <tbb/tbb.h>
46#endif
47
48namespace PTL
49{
50class ThreadPool;
51
52//--------------------------------------------------------------------------------------//
53
54#if !defined(PTL_DEFAULT_OBJECT)
55# define PTL_DEFAULT_OBJECT(NAME) \
56 NAME() = default; \
57 ~NAME() = default; \
58 NAME(const NAME&) = default; \
59 NAME(NAME&&) noexcept = default; \
60 NAME& operator=(const NAME&) = default; \
61 NAME& operator=(NAME&&) noexcept = default;
62#endif
63
64//--------------------------------------------------------------------------------------//
65
66template <typename JoinT, typename JoinArg>
68{
69public:
70 using Type = std::function<JoinT(JoinT&, JoinArg&&)>;
71
72public:
74
75 template <typename Func>
76 JoinFunction(Func&& func)
77 : m_func(std::forward<Func>(func))
78 {}
79
80 template <typename... Args>
81 JoinT& operator()(Args&&... args)
82 {
83 return std::move(m_func(std::forward<Args>(args)...));
84 }
85
86private:
87 Type m_func = [](JoinT& lhs, JoinArg&&) { return lhs; };
88};
89
90//--------------------------------------------------------------------------------------//
91
92template <typename JoinArg>
93struct JoinFunction<void, JoinArg>
94{
95public:
96 using Type = std::function<void(JoinArg)>;
97
98public:
100
101 template <typename Func>
102 JoinFunction(Func&& func)
103 : m_func(std::forward<Func>(func))
104 {}
105
106 template <typename... Args>
107 void operator()(Args&&... args)
108 {
109 m_func(std::forward<Args>(args)...);
110 }
111
112private:
113 Type m_func = [](JoinArg) {};
114};
115
116//--------------------------------------------------------------------------------------//
117
118template <>
119struct JoinFunction<void, void>
120{
121public:
122 using Type = std::function<void()>;
123
124public:
126
127 template <typename Func>
128 JoinFunction(Func&& func)
129 : m_func(std::forward<Func>(func))
130 {}
131
132 void operator()() { m_func(); }
133
134private:
135 Type m_func = []() {};
136};
137
138//--------------------------------------------------------------------------------------//
139
140template <typename Tp, typename Arg = Tp>
142: public VTaskGroup
143, public TaskAllocator<TaskGroup<Tp, Arg>>
144{
145public:
146 //------------------------------------------------------------------------//
148 typedef Tp result_type;
150 typedef std::promise<ArgTp> promise_type;
151 typedef std::future<ArgTp> future_type;
152 typedef std::packaged_task<ArgTp()> packaged_task_type;
155 typedef typename task_list_t::iterator iterator;
156 typedef typename task_list_t::reverse_iterator reverse_iterator;
157 typedef typename task_list_t::const_iterator const_iterator;
158 typedef typename task_list_t::const_reverse_iterator const_reverse_iterator;
159 //------------------------------------------------------------------------//
160 template <typename... Args>
162 //------------------------------------------------------------------------//
163
164public:
165 // Constructor
166 template <typename Func>
167 TaskGroup(Func&& _join, ThreadPool* _tp = nullptr)
168 : VTaskGroup(_tp)
169 , m_join(std::forward<Func>(_join))
170 {}
171 template <typename Up = Tp, enable_if_t<std::is_same<Up, void>::value, int> = 0>
172 explicit TaskGroup(ThreadPool* _tp = nullptr)
173 : VTaskGroup(_tp)
174 , m_join([]() {})
175 {}
176 // Destructor
177 virtual ~TaskGroup() { this->clear(); }
178
179 // delete copy-construct
180 TaskGroup(const this_type&) = delete;
181 // define move-construct
182 TaskGroup(this_type&& rhs) = default;
183 // delete copy-assign
184 this_type& operator=(const this_type& rhs) = delete;
185 // define move-assign
186 this_type& operator=(this_type&& rhs) = default;
187
188public:
189 //------------------------------------------------------------------------//
190 template <typename Up>
191 Up* operator+=(Up* _task)
192 {
193 // store in list
194 vtask_list.push_back(_task);
195 // thread-safe increment of tasks in task group
196 operator++();
197 // add the future
198 m_task_set.push_back(std::move(_task->get_future()));
199 // return
200 return _task;
201 }
202
203public:
204 //------------------------------------------------------------------------//
205 template <typename Func, typename... Args>
206 task_type<Args...>* wrap(Func&& func, Args... args)
207 {
208 return operator+=(
209 new task_type<Args...>(this, std::forward<Func>(func), args...));
210 }
211
212public:
213 //------------------------------------------------------------------------//
214 template <typename Func, typename... Args>
215 void exec(Func&& func, Args... args)
216 {
217 m_pool->add_task(wrap(std::forward<Func>(func), args...));
218 }
219 //------------------------------------------------------------------------//
220 template <typename Func, typename... Args>
221 void run(Func&& func, Args... args)
222 {
223 m_pool->add_task(wrap(std::forward<Func>(func), args...));
224 }
225 //------------------------------------------------------------------------//
226 template <typename Func, typename... Args>
227 void parallel_for(const intmax_t& nitr, const intmax_t& chunks, Func&& func,
228 Args... args)
229 {
230 auto nsplit = nitr / chunks;
231 auto nmod = nitr % chunks;
232 if(nsplit < 1)
233 nsplit = 1;
234 for(intmax_t n = 0; n < nsplit; ++n)
235 {
236 auto _beg = n * chunks;
237 auto _end = (n + 1) * chunks + ((n + 1 == nsplit) ? nmod : 0);
238 run(std::forward<Func>(func), std::move(_beg), std::move(_end), args...);
239 }
240 }
241
242protected:
243 //------------------------------------------------------------------------//
244 // shorter typedefs
249
250public:
251 //------------------------------------------------------------------------//
252 // Get tasks with non-void return types
253 //
255 const task_list_t& get_tasks() const { return m_task_set; }
256
257 //------------------------------------------------------------------------//
258 // iterate over tasks with return type
259 //
260 itr_t begin() { return m_task_set.begin(); }
261 itr_t end() { return m_task_set.end(); }
262 citr_t begin() const { return m_task_set.begin(); }
263 citr_t end() const { return m_task_set.end(); }
264 citr_t cbegin() const { return m_task_set.begin(); }
265 citr_t cend() const { return m_task_set.end(); }
266 ritr_t rbegin() { return m_task_set.rbegin(); }
267 ritr_t rend() { return m_task_set.rend(); }
268 critr_t rbegin() const { return m_task_set.rbegin(); }
269 critr_t rend() const { return m_task_set.rend(); }
270
271 //------------------------------------------------------------------------//
272 // wait to finish
273 template <typename Up = Tp, enable_if_t<!std::is_void<Up>::value, int> = 0>
274 inline Up join(Up accum = {})
275 {
276 this->wait();
277 for(auto& itr : m_task_set)
278 {
279 using RetT = decay_t<decltype(itr.get())>;
280 accum = std::move(m_join(std::ref(accum), std::forward<RetT>(itr.get())));
281 }
282 this->clear();
283 return accum;
284 }
285 //------------------------------------------------------------------------//
286 // wait to finish
287 template <typename Up = Tp, typename Rp = Arg,
288 enable_if_t<std::is_void<Up>::value && std::is_void<Rp>::value, int> = 0>
289 inline void join()
290 {
291 this->wait();
292 for(auto& itr : m_task_set)
293 itr.get();
294 m_join();
295 this->clear();
296 }
297 //------------------------------------------------------------------------//
298 // wait to finish
299 template <typename Up = Tp, typename Rp = Arg,
300 enable_if_t<std::is_void<Up>::value && !std::is_void<Rp>::value, int> = 0>
301 inline void join()
302 {
303 this->wait();
304 for(auto& itr : m_task_set)
305 {
306 using RetT = decay_t<decltype(itr.get())>;
307 m_join(std::forward<RetT>(itr.get()));
308 }
309 this->clear();
310 }
311 //------------------------------------------------------------------------//
312 // clear the task result history
313 void clear()
314 {
315 m_task_set.clear();
317 }
318
319protected:
320 // Protected variables
323};
324
325} // namespace PTL
#define PTL_DEFAULT_OBJECT(NAME)
Definition: TaskGroup.hh:55
TaskGroup(ThreadPool *_tp=nullptr)
Definition: TaskGroup.hh:172
citr_t end() const
Definition: TaskGroup.hh:263
task_type< Args... > * wrap(Func &&func, Args... args)
Definition: TaskGroup.hh:206
citr_t cbegin() const
Definition: TaskGroup.hh:264
TaskGroup(Func &&_join, ThreadPool *_tp=nullptr)
Definition: TaskGroup.hh:167
const_iterator citr_t
Definition: TaskGroup.hh:246
Up join(Up accum={})
Definition: TaskGroup.hh:274
ritr_t rend()
Definition: TaskGroup.hh:267
const_reverse_iterator critr_t
Definition: TaskGroup.hh:248
ritr_t rbegin()
Definition: TaskGroup.hh:266
this_type & operator=(this_type &&rhs)=default
reverse_iterator ritr_t
Definition: TaskGroup.hh:247
std::future< ArgTp > future_type
Definition: TaskGroup.hh:151
itr_t begin()
Definition: TaskGroup.hh:260
task_list_t::const_reverse_iterator const_reverse_iterator
Definition: TaskGroup.hh:158
void exec(Func &&func, Args... args)
Definition: TaskGroup.hh:215
std::promise< ArgTp > promise_type
Definition: TaskGroup.hh:150
std::packaged_task< ArgTp()> packaged_task_type
Definition: TaskGroup.hh:152
TaskGroup(const this_type &)=delete
task_list_t & get_tasks()
Definition: TaskGroup.hh:254
JoinFunction< Tp, Arg >::Type join_type
Definition: TaskGroup.hh:154
Up * operator+=(Up *_task)
Definition: TaskGroup.hh:191
const task_list_t & get_tasks() const
Definition: TaskGroup.hh:255
this_type & operator=(const this_type &rhs)=delete
void parallel_for(const intmax_t &nitr, const intmax_t &chunks, Func &&func, Args... args)
Definition: TaskGroup.hh:227
task_list_t::const_iterator const_iterator
Definition: TaskGroup.hh:157
critr_t rbegin() const
Definition: TaskGroup.hh:268
task_list_t::iterator iterator
Definition: TaskGroup.hh:155
citr_t cend() const
Definition: TaskGroup.hh:265
critr_t rend() const
Definition: TaskGroup.hh:269
void run(Func &&func, Args... args)
Definition: TaskGroup.hh:221
virtual ~TaskGroup()
Definition: TaskGroup.hh:177
task_list_t m_task_set
Definition: TaskGroup.hh:321
list_type< future_type > task_list_t
Definition: TaskGroup.hh:153
decay_t< Arg > ArgTp
Definition: TaskGroup.hh:147
iterator itr_t
Definition: TaskGroup.hh:245
TaskGroup(this_type &&rhs)=default
join_type m_join
Definition: TaskGroup.hh:322
TaskGroup< Tp, Arg > this_type
Definition: TaskGroup.hh:149
citr_t begin() const
Definition: TaskGroup.hh:262
task_list_t::reverse_iterator reverse_iterator
Definition: TaskGroup.hh:156
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
vtask_list_type vtask_list
Definition: VTaskGroup.hh:141
ThreadPool * m_pool
Definition: VTaskGroup.hh:136
virtual void wait()
Definition: VTaskGroup.cc:81
std::vector< Tp > list_type
Definition: VTaskGroup.hh:59
intmax_t operator++()
Definition: VTaskGroup.hh:92
Definition: AutoLock.hh:254
typename std::decay< T >::type decay_t
Definition: Globals.hh:52
typename std::enable_if< B, T >::type enable_if_t
Definition: Globals.hh:55
std::function< void(JoinArg)> Type
Definition: TaskGroup.hh:96
void operator()(Args &&... args)
Definition: TaskGroup.hh:107
std::function< void()> Type
Definition: TaskGroup.hh:122
JoinT & operator()(Args &&... args)
Definition: TaskGroup.hh:81
JoinFunction(Func &&func)
Definition: TaskGroup.hh:76
std::function< JoinT(JoinT &, JoinArg &&)> Type
Definition: TaskGroup.hh:70