From 3b9f9baef9c27e4d22ebeff59118aaddaa40e9f2 Mon Sep 17 00:00:00 2001 From: Konstantin Boyarinov Date: Wed, 13 Dec 2023 16:21:59 +0200 Subject: [PATCH] Fix parallel_for_each iterator tag dispatch for move iterators + fix stack overflow on Windows (#1276) --- include/oneapi/tbb/parallel_for_each.h | 21 ++++++++++++++++++- .../conformance_parallel_for_each.cpp | 2 -- test/tbb/test_parallel_for_each.cpp | 6 +++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/include/oneapi/tbb/parallel_for_each.h b/include/oneapi/tbb/parallel_for_each.h index f9c169c8c4..ab0b345388 100644 --- a/include/oneapi/tbb/parallel_for_each.h +++ b/include/oneapi/tbb/parallel_for_each.h @@ -409,12 +409,31 @@ using tag = typename std::iterator_traits::iterator_category; #if __TBB_CPP20_PRESENT template -using iterator_tag_dispatch = +struct move_iterator_dispatch_helper { + using type = It; +}; + +// Until C++23, std::move_iterator::iterator_concept always defines +// to std::input_iterator_tag and hence std::forward_iterator concept +// always evaluates to false, so std::move_iterator dispatch should be +// made according to the base iterator type. +template +struct move_iterator_dispatch_helper> { + using type = It; +}; + +template +using iterator_tag_dispatch_impl = std::conditional_t, std::random_access_iterator_tag, std::conditional_t, std::forward_iterator_tag, std::input_iterator_tag>>; + +template +using iterator_tag_dispatch = + iterator_tag_dispatch_impl::type>; + #else template using iterator_tag_dispatch = typename diff --git a/test/conformance/conformance_parallel_for_each.cpp b/test/conformance/conformance_parallel_for_each.cpp index ad8ee672f7..e36a2803cf 100644 --- a/test/conformance/conformance_parallel_for_each.cpp +++ b/test/conformance/conformance_parallel_for_each.cpp @@ -102,10 +102,8 @@ class ForEachInvokeItem { void do_action_and_feed(oneapi::tbb::feeder& feeder) const { CHECK_MESSAGE(change_vector.size() % 2 == 0, "incorrect test setup"); std::size_t shift = change_vector.size() / 2; - std::cout << "Process " << real_value << std::endl; ++change_vector[real_value]; if (real_value < shift) { - std::cout << "Add " << real_value + shift << std::endl; feeder.add(ForEachInvokeItem(real_value + shift, change_vector)); } } diff --git a/test/tbb/test_parallel_for_each.cpp b/test/tbb/test_parallel_for_each.cpp index ccaf12d4cb..3dfc107e91 100644 --- a/test/tbb/test_parallel_for_each.cpp +++ b/test/tbb/test_parallel_for_each.cpp @@ -290,10 +290,10 @@ template void test_with_cpp20_iterator() { constexpr std::size_t n = 1'000'000; - no_copy_move elements[n]; + std::vector elements(n); - cpp20_iterator begin(elements); - cpp20_iterator end(elements + n); + cpp20_iterator begin(elements.data()); + cpp20_iterator end(elements.data() + n); oneapi::tbb::parallel_for_each(begin, end, [](no_copy_move& element) { element.item = 42;