17#ifndef __algo_threaded_loop_h__
18#define __algo_threaded_loop_h__
245 inline vector<size_t> get_inner_axes (
const vector<size_t>& axes,
size_t num_inner_axes) {
246 return { axes.begin(), axes.begin()+num_inner_axes };
249 inline vector<size_t> get_outer_axes (
const vector<size_t>& axes,
size_t num_inner_axes) {
250 return { axes.begin()+num_inner_axes, axes.end() };
253 template <
class HeaderType>
254 inline vector<size_t> get_inner_axes (
const HeaderType& source,
size_t num_inner_axes,
size_t from_axis,
size_t to_axis) {
255 return get_inner_axes (
Stride::order (source, from_axis, to_axis), num_inner_axes);
258 template <
class HeaderType>
259 inline vector<size_t> get_outer_axes (
const HeaderType& source,
size_t num_inner_axes,
size_t from_axis,
size_t to_axis) {
260 return get_outer_axes (
Stride::order (source, from_axis, to_axis), num_inner_axes);
264 template <
int N,
class Functor,
class... ImageType>
265 struct ThreadedLoopRunInner
266 {
MEMALIGN(ThreadedLoopRunInner<N,Functor,ImageType...>)
267 const vector<size_t>& outer_axes;
268 decltype (
Loop (outer_axes)) loop;
269 typename std::remove_reference<Functor>::type func;
270 std::tuple<ImageType...> vox;
272 ThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
273 const Functor&
functor, ImageType&... voxels) :
274 outer_axes (outer_axes),
275 loop (
Loop (inner_axes)),
279 void operator() (
const Iterator& pos) {
280 assign_pos_of (pos, outer_axes).to (vox);
281 for (
auto i =
unpack (loop, vox); i; ++i)
287 template <
class Functor,
class... ImageType>
288 struct ThreadedLoopRunInner<0,Functor,ImageType...>
289 {
MEMALIGN(ThreadedLoopRunInner<0, Functor,ImageType...>)
290 const vector<size_t>& outer_axes;
291 decltype (
Loop (outer_axes)) loop;
292 typename std::remove_reference<Functor>::type func;
294 ThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
295 const Functor&
functor, ImageType&... ) :
296 outer_axes (outer_axes),
297 loop (
Loop (inner_axes)),
300 void operator() (Iterator& pos) {
301 for (
auto i = loop (pos); i; ++i)
307 inline void __manage_progress (...) { }
308 template <
class LoopType,
class ThreadType>
309 inline auto __manage_progress (
const LoopType* loop,
const ThreadType*
threads)
310 ->
decltype((void) (&loop->progress), void())
312 loop->progress.run_update_thread (*
threads);
316 template <
class OuterLoopType>
317 struct ThreadedLoopRunOuter {
MEMALIGN(ThreadedLoopRunOuter<OuterLoopType>)
319 OuterLoopType outer_loop;
320 vector<size_t> inner_axes;
323 template <
class Functor>
324 void run_outer (Functor&&
functor)
327 for (
auto i = outer_loop (iterator); i; ++i)
333 ProgressBar::SwitchToMultiThreaded progress_functions;
337 decltype (outer_loop (iterator)) loop;
340 std::lock_guard<std::mutex> lock (mutex);
342 assign_pos_of (iterator, loop.axes).to (pos);
348 } shared = { iterator, outer_loop (iterator), mutex };
350 struct PerThread {
MEMALIGN(PerThread)
352 typename std::remove_reference<Functor>::type func;
354 Iterator pos = shared.iterator;
355 while (shared.next (pos))
358 } loop_thread = { shared,
functor };
362 __manage_progress (&shared.loop, &
threads);
369 template <
class Functor,
class... ImageType>
370 void run (Functor&&
functor, ImageType&&... vox)
372 ThreadedLoopRunInner<
373 sizeof...(ImageType),
374 typename std::remove_reference<Functor>::type,
375 typename std::remove_reference<ImageType>::type...
376 > loop_thread (outer_loop.axes, inner_axes,
functor, vox...);
377 run_outer (loop_thread);
392 template <
class HeaderType>
393 inline ThreadedLoopRunOuter<decltype(Loop(vector<size_t>()))>
395 const HeaderType& source,
398 {
return { source,
Loop (outer_axes), inner_axes }; }
403 template <
class HeaderType>
404 inline ThreadedLoopRunOuter<decltype(Loop(vector<size_t>()))>
406 const HeaderType& source,
408 size_t num_inner_axes = 1)
409 {
return { source,
Loop (get_outer_axes (axes, num_inner_axes)), get_inner_axes (axes, num_inner_axes) }; }
413 template <
class HeaderType>
414 inline ThreadedLoopRunOuter<decltype(Loop(vector<size_t>()))>
416 const HeaderType& source,
417 size_t from_axis = 0,
418 size_t to_axis = std::numeric_limits<size_t>::max(),
419 size_t num_inner_axes = 1)
422 Loop (get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
423 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
428 template <
class HeaderType>
429 inline ThreadedLoopRunOuter<
decltype(
Loop(
"", vector<size_t>()))>
431 const std::string& progress_message,
432 const HeaderType& source,
435 {
return { source,
Loop (progress_message, outer_axes), inner_axes }; }
439 template <
class HeaderType>
440 inline ThreadedLoopRunOuter<
decltype(
Loop(
"", vector<size_t>()))>
442 const std::string& progress_message,
443 const HeaderType& source,
445 size_t num_inner_axes = 1)
448 Loop (progress_message, get_outer_axes (axes, num_inner_axes)),
449 get_inner_axes (axes, num_inner_axes) };
454 template <
class HeaderType>
455 inline ThreadedLoopRunOuter<
decltype(
Loop(
"", vector<size_t>()))>
457 const std::string& progress_message,
458 const HeaderType& source,
459 size_t from_axis = 0,
460 size_t to_axis = std::numeric_limits<size_t>::max(),
461 size_t num_inner_axes = 1)
464 Loop (progress_message, get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
465 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
FORCE_INLINE LoopAlongAxes Loop()
__run< Functor >::type run(Functor &&functor, const std::string &name="unnamed")
Execute the functor's execute method in a separate thread.
size_t threads_to_execute()
__Multi< typename std::remove_reference< Functor >::type > multi(Functor &&functor, size_t nthreads=threads_to_execute())
used to request multiple threads of the corresponding functor
vector< size_t > order(const HeaderType &header, size_t from_axis=0, size_t to_axis=std::numeric_limits< size_t >::max())
sort range of axes with respect to their absolute stride.
ThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> ThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
Multi-threaded loop object.
auto unpack(F &&f, T &&t) -> decltype(Unpack< ::std::tuple_size< typename ::std::decay< T >::type >::value >::unpack(::std::forward< F >(f), ::std::forward< T >(t)))
if t is a tuple of elements a..., invoke f(a...)
void check_app_exit_code()
vector< std::future< void > > threads
std::remove_reference< Functor >::type & functor