/* Copyright (c) 2005-2023 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "common/parallel_for_each_common.h" //! \file conformance_parallel_for_each.cpp //! \brief Test for [algorithms.parallel_for_each] specification //! Test input access iterator support //! \brief \ref requirement \ref interface TEST_CASE("Input iterator support") { for ( auto concurrency_level : utils::concurrency_range() ) { oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, concurrency_level); for( size_t depth = 0; depth <= depths_nubmer; ++depth ) { g_tasks_expected = 0; for ( size_t i=0; i < depth; ++i ) g_tasks_expected += FindNumOfTasks(g_depths[i].value()); TestIterator_Const>(depth); TestIterator_Move>(depth); #if __TBB_CPP14_GENERIC_LAMBDAS_PRESENT TestGenericLambdasCommon>(depth); #endif } } } //! Test container based overload //! \brief \ref requirement \ref interface TEST_CASE("Container based overload - input iterator based container") { container_based_overload_test_case(/*expected_value*/0); } const size_t elements = 10000; const size_t init_sum = 0; std::atomic element_counter; template struct set_to { void operator()(size_t& x) const { x = K; ++element_counter; } }; #include "common/range_based_for_support.h" #include #include template void WorkProducingTest(Context&... context) { for ( auto concurrency_level : utils::concurrency_range() ) { oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, concurrency_level); using namespace range_based_for_support_tests; std::deque v(elements, 0); element_counter = 0; oneapi::tbb::parallel_for_each(v.begin(), v.end(), set_to<0>(), context...); REQUIRE_MESSAGE((element_counter == v.size() && element_counter == elements), "not all elements were set"); REQUIRE_MESSAGE(range_based_for_accumulate(v, std::plus(), init_sum) == init_sum, "elements of v not all ones"); element_counter = 0; oneapi::tbb::parallel_for_each(v, set_to<1>(), context...); REQUIRE_MESSAGE((element_counter == v.size() && element_counter == elements), "not all elements were set"); REQUIRE_MESSAGE(range_based_for_accumulate(v, std::plus(), init_sum) == v.size(), "elements of v not all ones"); element_counter = 0; oneapi::tbb::parallel_for_each(oneapi::tbb::blocked_range::iterator>(v.begin(), v.end()), set_to<0>(), context...); REQUIRE_MESSAGE((element_counter == v.size() && element_counter == elements), "not all elements were set"); REQUIRE_MESSAGE(range_based_for_accumulate(v, std::plus(), init_sum) == init_sum, "elements of v not all zeros"); } } #if __TBB_CPP17_INVOKE_PRESENT class ForEachInvokeItem { public: ForEachInvokeItem(std::size_t rv, std::vector& cv) : real_value(rv), change_vector(cv) {} void do_action() const { ++change_vector[real_value]; } 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; ++change_vector[real_value]; if (real_value < shift) { feeder.add(ForEachInvokeItem(real_value + shift, change_vector)); } } private: std::size_t real_value; std::vector& change_vector; }; template