1 /* 2 Copyright (c) 2005-2021 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #include "common/test.h" 18 #include "common/utils.h" 19 20 #include "oneapi/tbb/task_arena.h" 21 #include "oneapi/tbb/task_scheduler_observer.h" 22 #include "oneapi/tbb/enumerable_thread_specific.h" 23 #include "oneapi/tbb/parallel_for.h" 24 25 //! \file conformance_task_arena.cpp 26 //! \brief Test for [scheduler.task_arena scheduler.task_scheduler_observer] specification 27 28 // This test requires TBB in an uninitialized state 29 //! Test for uninitilized arena 30 //! \brief \ref requirement \ref interface 31 TEST_CASE("Test current_thread_index") { 32 REQUIRE_MESSAGE((tbb::this_task_arena::current_thread_index() == tbb::task_arena::not_initialized), "TBB was initialized state"); 33 } 34 35 //! Test task arena interfaces 36 //! \brief \ref requirement \ref interface 37 TEST_CASE("Arena interfaces") { 38 //! Initialization interfaces 39 oneapi::tbb::task_arena a(1,1); a.initialize(); 40 std::atomic<bool> done{ false }; 41 //! Enqueue interface 42 a.enqueue([&done] { 43 CHECK(oneapi::tbb::this_task_arena::max_concurrency() == 2); 44 done = true; 45 }); 46 //! Execute interface 47 a.execute([&] { 48 //! oneapi::tbb::this_task_arena interfaces 49 CHECK(oneapi::tbb::this_task_arena::current_thread_index() >= 0); 50 //! Attach interface 51 oneapi::tbb::task_arena attached_arena{oneapi::tbb::task_arena::attach()}; 52 CHECK(attached_arena.is_active()); 53 }); 54 while (!done) { 55 utils::yield(); 56 } 57 //! Terminate interface 58 a.terminate(); 59 } 60 61 //! Test tasks isolation for inner oneapi::tbb::parallel_for loop 62 //! \brief \ref requirement \ref interface 63 TEST_CASE("Task isolation") { 64 const int N1 = 1000, N2 = 1000; 65 oneapi::tbb::enumerable_thread_specific<int> ets; 66 oneapi::tbb::parallel_for(0, N1, [&](int i) { 67 // Set a thread specific value 68 ets.local() = i; 69 // Run the second parallel loop in an isolated region to prevent the current thread 70 // from taking tasks related to the outer parallel loop. 71 oneapi::tbb::this_task_arena::isolate([&]{ 72 oneapi::tbb::parallel_for(0, N2, utils::DummyBody(10)); 73 }); 74 REQUIRE(ets.local() == i); 75 }); 76 } 77 78 class conformance_observer: public oneapi::tbb::task_scheduler_observer { 79 public: 80 std::atomic<bool> is_entry_called{false}; 81 std::atomic<bool> is_exit_called{false}; 82 83 conformance_observer( oneapi::tbb::task_arena &a ) : oneapi::tbb::task_scheduler_observer(a) { 84 observe(true); // activate the observer 85 } 86 87 void on_scheduler_entry(bool) override { 88 is_entry_called.store(true, std::memory_order_relaxed); 89 } 90 91 void on_scheduler_exit(bool) override { 92 is_exit_called.store(true, std::memory_order_relaxed); 93 } 94 95 bool is_callbacks_called() { 96 return is_entry_called.load(std::memory_order_relaxed) 97 && is_exit_called.load(std::memory_order_relaxed); 98 } 99 }; 100 101 //! Test task arena observer interfaces 102 //! \brief \ref requirement \ref interface 103 TEST_CASE("Task arena observer") { 104 oneapi::tbb::task_arena a; a.initialize(); 105 conformance_observer observer(a); 106 a.execute([&] { 107 oneapi::tbb::parallel_for(0, 100, utils::DummyBody(10), oneapi::tbb::simple_partitioner()); 108 }); 109 REQUIRE(observer.is_callbacks_called()); 110 } 111 112 //! Test task arena copy constructor 113 //! \brief \ref interface \ref requirement 114 TEST_CASE("Task arena copy constructor") { 115 oneapi::tbb::task_arena arena(1); 116 oneapi::tbb::task_arena copy = arena; 117 118 REQUIRE(arena.max_concurrency() == copy.max_concurrency()); 119 REQUIRE(arena.is_active() == copy.is_active()); 120 } 121