#ifndef EXECUTIONTBB_HPP #define EXECUTIONTBB_HPP #include #include #include #include #include #include "Execution.hpp" namespace Slic3r { struct ExecutionTBB {}; template<> struct IsExecutionPolicy_ : public std::true_type {}; // Execution policy using Intel TBB library under the hood. static constexpr ExecutionTBB ex_tbb = {}; template<> struct execution::Traits { private: template static IteratorOnly loop_(const tbb::blocked_range &range, Fn &&fn) { for (auto &el : range) fn(el); } template static IntegerOnly loop_(const tbb::blocked_range &range, Fn &&fn) { for (I i = range.begin(); i < range.end(); ++i) fn(i); } public: using SpinningMutex = tbb::spin_mutex; using BlockingMutex = std::mutex; template static void for_each(const ExecutionTBB &, It from, It to, Fn &&fn, size_t granularity) { tbb::parallel_for(tbb::blocked_range{from, to, granularity}, [&fn](const auto &range) { loop_(range, std::forward(fn)); }); } template static T reduce(const ExecutionTBB &, I from, I to, const T &init, MergeFn &&mergefn, AccessFn &&access, size_t granularity = 1 ) { return tbb::parallel_reduce( tbb::blocked_range{from, to, granularity}, init, [&](const auto &range, T subinit) { T acc = subinit; loop_(range, [&](auto &i) { acc = mergefn(acc, access(i)); }); return acc; }, std::forward(mergefn)); } static size_t max_concurrency(const ExecutionTBB &) { return tbb::this_task_arena::max_concurrency(); } }; } #endif // EXECUTIONTBB_HPP