1 #ifndef SLA_CONCURRENCY_H 2 #define SLA_CONCURRENCY_H 3 4 #include <tbb/spin_mutex.h> 5 #include <mutex> 6 #include <tbb/parallel_for.h> 7 #include <tbb/parallel_reduce.h> 8 9 #include <algorithm> 10 #include <numeric> 11 12 #include <libslic3r/libslic3r.h> 13 14 namespace Slic3r { 15 namespace sla { 16 17 // Set this to true to enable full parallelism in this module. 18 // Only the well tested parts will be concurrent if this is set to false. 19 const constexpr bool USE_FULL_CONCURRENCY = true; 20 21 template<bool> struct _ccr {}; 22 23 template<> struct _ccr<true> 24 { 25 using SpinningMutex = tbb::spin_mutex; 26 using BlockingMutex = std::mutex; 27 28 template<class Fn, class It> loop_Slic3r::sla::_ccr29 static IteratorOnly<It, void> loop_(const tbb::blocked_range<It> &range, Fn &&fn) 30 { 31 for (auto &el : range) fn(el); 32 } 33 34 template<class Fn, class I> loop_Slic3r::sla::_ccr35 static IntegerOnly<I, void> loop_(const tbb::blocked_range<I> &range, Fn &&fn) 36 { 37 for (I i = range.begin(); i < range.end(); ++i) fn(i); 38 } 39 40 template<class It, class Fn> for_eachSlic3r::sla::_ccr41 static void for_each(It from, It to, Fn &&fn, size_t granularity = 1) 42 { 43 tbb::parallel_for(tbb::blocked_range{from, to, granularity}, 44 [&fn, from](const auto &range) { 45 loop_(range, std::forward<Fn>(fn)); 46 }); 47 } 48 49 template<class I, class MergeFn, class T, class AccessFn> reduceSlic3r::sla::_ccr50 static T reduce(I from, 51 I to, 52 const T &init, 53 MergeFn &&mergefn, 54 AccessFn &&access, 55 size_t granularity = 1 56 ) 57 { 58 return tbb::parallel_reduce( 59 tbb::blocked_range{from, to, granularity}, init, 60 [&](const auto &range, T subinit) { 61 T acc = subinit; 62 loop_(range, [&](auto &i) { acc = mergefn(acc, access(i)); }); 63 return acc; 64 }, 65 std::forward<MergeFn>(mergefn)); 66 } 67 68 template<class I, class MergeFn, class T> reduceSlic3r::sla::_ccr69 static IteratorOnly<I, T> reduce(I from, 70 I to, 71 const T & init, 72 MergeFn &&mergefn, 73 size_t granularity = 1) 74 { 75 return reduce( 76 from, to, init, std::forward<MergeFn>(mergefn), 77 [](typename I::value_type &i) { return i; }, granularity); 78 } 79 }; 80 81 template<> struct _ccr<false> 82 { 83 private: unlockSlic3r::sla::_ccr::_Mtx84 struct _Mtx { inline void lock() {} inline void unlock() {} }; 85 86 public: 87 using SpinningMutex = _Mtx; 88 using BlockingMutex = _Mtx; 89 90 template<class Fn, class It> loop_Slic3r::sla::_ccr91 static IteratorOnly<It, void> loop_(It from, It to, Fn &&fn) 92 { 93 for (auto it = from; it != to; ++it) fn(*it); 94 } 95 96 template<class Fn, class I> loop_Slic3r::sla::_ccr97 static IntegerOnly<I, void> loop_(I from, I to, Fn &&fn) 98 { 99 for (I i = from; i < to; ++i) fn(i); 100 } 101 102 template<class It, class Fn> for_eachSlic3r::sla::_ccr103 static void for_each(It from, 104 It to, 105 Fn &&fn, 106 size_t /* ignore granularity */ = 1) 107 { 108 loop_(from, to, std::forward<Fn>(fn)); 109 } 110 111 template<class I, class MergeFn, class T, class AccessFn> reduceSlic3r::sla::_ccr112 static T reduce(I from, 113 I to, 114 const T & init, 115 MergeFn &&mergefn, 116 AccessFn &&access, 117 size_t /*granularity*/ = 1 118 ) 119 { 120 T acc = init; 121 loop_(from, to, [&](auto &i) { acc = mergefn(acc, access(i)); }); 122 return acc; 123 } 124 125 template<class I, class MergeFn, class T> reduceSlic3r::sla::_ccr126 static IteratorOnly<I, T> reduce(I from, 127 I to, 128 const T &init, 129 MergeFn &&mergefn, 130 size_t /*granularity*/ = 1 131 ) 132 { 133 return reduce(from, to, init, std::forward<MergeFn>(mergefn), 134 [](typename I::value_type &i) { return i; }); 135 } 136 }; 137 138 using ccr = _ccr<USE_FULL_CONCURRENCY>; 139 using ccr_seq = _ccr<false>; 140 using ccr_par = _ccr<true>; 141 142 }} // namespace Slic3r::sla 143 144 #endif // SLACONCURRENCY_H 145