126#ifdef SUBPAR_CUSTOM_PARALLELIZE_RANGE
127 if constexpr(nothrow_) {
128#ifdef SUBPAR_CUSTOM_PARALLELIZE_RANGE_NOTHROW
129 return SUBPAR_CUSTOM_PARALLELIZE_RANGE_NOTHROW(num_workers, num_tasks, run_task_range);
131 return SUBPAR_CUSTOM_PARALLELIZE_RANGE(num_workers, num_tasks, run_task_range);
134 return SUBPAR_CUSTOM_PARALLELIZE_RANGE(num_workers, num_tasks, run_task_range);
138 if (num_tasks <= 0) {
142 if (num_workers <= 1 || num_tasks == 1) {
143 run_task_range(0, 0, num_tasks);
148 Task_ tasks_per_worker = 1;
150 if (sanisizer::is_greater_than_or_equal(num_workers, num_tasks)) {
151 num_workers = num_tasks;
153 tasks_per_worker = num_tasks / num_workers;
154 remainder = num_tasks % num_workers;
157 const auto get_start = [&tasks_per_worker,&remainder](
const int w) -> Task_ {
159 return w * tasks_per_worker + (w < remainder ? w : remainder);
162 const auto get_length = [&tasks_per_worker,&remainder](
const int w) -> Task_ {
163 return tasks_per_worker + (w < remainder);
168 if constexpr(nothrow_) {
171 return sanisizer::create<std::vector<std::exception_ptr> >(num_workers);
175#if defined(_OPENMP) && !defined(SUBPAR_NO_OPENMP_RANGE) && !defined(SUBPAR_NO_OPENMP)
176#define SUBPAR_USES_OPENMP 1
177#define SUBPAR_USES_OPENMP_RANGE 1
181 #pragma omp parallel for num_threads(num_workers)
182 for (
int w = 0; w < num_workers; ++w) {
183 const Task_ start = get_start(w);
184 const Task_ length = get_length(w);
186 if constexpr(nothrow_) {
187 run_task_range(w, start, length);
190 run_task_range(w, start, length);
192 errors[w] = std::current_exception();
199#undef SUBPAR_USES_OPENMP
200#undef SUBPAR_USES_OPENMP_RANGE
203 std::vector<std::thread> workers;
204 sanisizer::reserve(workers, num_workers - 1);
206 for (
int w = 1; w < num_workers; ++w) {
207 const Task_ start = get_start(w);
208 const Task_ length = get_length(w);
210 if constexpr(nothrow_) {
211 workers.emplace_back(run_task_range, w, start, length);
213 workers.emplace_back([&run_task_range,&errors](
int w, Task_ start, Task_ length) ->
void {
215 run_task_range(w, start, length);
217 errors[w] = std::current_exception();
219 }, w, start, length);
224 const Task_ start = get_start(0);
225 const Task_ length = get_length(0);
227 if constexpr(nothrow_) {
228 run_task_range(0, start, length);
231 run_task_range(0, start, length);
233 errors[0] = std::current_exception();
238 for (
auto& wrk : workers) {
243 if constexpr(!nothrow_) {
244 for (
const auto& e : errors) {
246 std::rethrow_exception(e);