Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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