From 7f1cba66105103a26b6c2d1ca98c3ea86e0d431c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 3 Nov 2021 16:56:39 +0100 Subject: 'Manual' parallel for loop. Since not all compilers implement the full C++17 yet, specifically the Parallel Execution TS wasn't added to their respective libraries yet. done as part of CURA-8573 --- src/utils/algorithm.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'src/utils/algorithm.h') diff --git a/src/utils/algorithm.h b/src/utils/algorithm.h index 3cc2fe2d8..adb130ef3 100644 --- a/src/utils/algorithm.h +++ b/src/utils/algorithm.h @@ -1,11 +1,13 @@ -/** Copyright (C) 2016 Ultimaker - Released under terms of the AGPLv3 License */ +/** Copyright (C) 2021 Ultimaker - Released under terms of the AGPLv3 License */ #ifndef UTILS_ALGORITHM_H #define UTILS_ALGORITHM_H #include -#include +#include #include +#include #include +#include // extensions to algorithm.h from the standard library @@ -41,6 +43,54 @@ std::vector order(const std::vector &in) return order; } +/* An implementation of parallel for. + * There are still a lot of compilers that claim to be fully C++17 compatible, but don't implement the Parallel Execution TS of the accompanying standard lybrary. + * This means that we moslty have to fall back to the things that C++11/14 provide when it comes to threading/parallelism/etc. + * + * \param from The index starts here (inclusive). + * \param to The index ends here (not inclusive). + * \param increment Add this to the index each time. + * \param body The loop-body, as a closure. Receives the index on invocation. + */ +template +void parallel_for(T from, T to, T increment, const std::function& body) +{ + // Sanity tests. + assert(increment > 0); + assert(from <= to); + + // Set the values so that 'to' is a whole integer multiple apart from 'from' (& early out if needed). + to = from + increment * (((to - from) + (increment - static_cast(1))) / increment); + if (to == from) + { + return; + } + + // Set an atomic countdown variable to how many tasks need to be completed. + std::atomic tasks_pending((to - from) / increment); + + // Wrap the loop-body, so that the outer scope can be notified by 'all_tasks_done'. + std::promise all_tasks_done; + const auto func = + [&body, &tasks_pending, &all_tasks_done](const T index) + { + body(index); + if (--tasks_pending == 0) + { + all_tasks_done.set_value(); + } + }; + + // Run all tasks. + for (size_t index = from; index != to; index += increment) + { + std::async(std::launch::async, func, index); + } + + // Wait for the end-result before return. + all_tasks_done.get_future().wait(); +} + } // namespace cura #endif // UTILS_ALGORITHM_H -- cgit v1.2.3