149e08aacStbbdev /*
2b15aabb3Stbbdev     Copyright (c) 2020-2021 Intel Corporation
349e08aacStbbdev 
449e08aacStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
549e08aacStbbdev     you may not use this file except in compliance with the License.
649e08aacStbbdev     You may obtain a copy of the License at
749e08aacStbbdev 
849e08aacStbbdev         http://www.apache.org/licenses/LICENSE-2.0
949e08aacStbbdev 
1049e08aacStbbdev     Unless required by applicable law or agreed to in writing, software
1149e08aacStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1249e08aacStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349e08aacStbbdev     See the License for the specific language governing permissions and
1449e08aacStbbdev     limitations under the License.
1549e08aacStbbdev */
1649e08aacStbbdev 
17478de5b1Stbbdev #if _WIN32 || _WIN64
18478de5b1Stbbdev #define _CRT_SECURE_NO_WARNINGS
19478de5b1Stbbdev #endif
20478de5b1Stbbdev 
21b15aabb3Stbbdev #if _MSC_VER && !defined(__INTEL_COMPILER)
22b15aabb3Stbbdev // structure was padded due to alignment specifier
23b15aabb3Stbbdev #pragma warning( disable: 4324 )
24b15aabb3Stbbdev #endif
25b15aabb3Stbbdev 
2649e08aacStbbdev #include "common/test.h"
2749e08aacStbbdev #include "common/utils.h"
2849e08aacStbbdev #include "common/utils_concurrency_limit.h"
2949e08aacStbbdev #include "common/spin_barrier.h"
3049e08aacStbbdev 
3149e08aacStbbdev #include "tbb/global_control.h"
3249e08aacStbbdev #include "tbb/task_arena.h"
3349e08aacStbbdev #include "../../src/tbb/concurrent_monitor.h"
344523a761Stbbdev #include "../../src/tbb/misc.cpp"
3549e08aacStbbdev 
3649e08aacStbbdev //! \file test_concurrent_monitor.cpp
3749e08aacStbbdev //! \brief Test for [internal] functionality
3849e08aacStbbdev 
3949e08aacStbbdev #if TBB_USE_EXCEPTIONS
4049e08aacStbbdev //! \brief \ref error_guessing
4149e08aacStbbdev TEST_CASE("Stress test") {
4249e08aacStbbdev     enum class notification_types {
4349e08aacStbbdev         notify,
4449e08aacStbbdev         notify_one,
4549e08aacStbbdev         notify_all,
4649e08aacStbbdev         notify_number
4749e08aacStbbdev     };
4849e08aacStbbdev 
4949e08aacStbbdev     std::size_t threads_number = utils::get_platform_max_threads();
5049e08aacStbbdev 
5149e08aacStbbdev     // Need to prolong lifetime of the exposed concurrent_monitor
52*5fc0a5f6SAlex     tbb::task_scheduler_handle handler{tbb::attach{}};
5349e08aacStbbdev 
548b6f831cStbbdev     utils::SpinBarrier barrier(threads_number);
558b6f831cStbbdev 
56d86ed7fbStbbdev     tbb::detail::r1::concurrent_monitor test_monitor;
5749e08aacStbbdev     {
5855f9b178SIvan Kochin         tbb::task_arena arena(static_cast<int>(threads_number - 1), 0);
598b6f831cStbbdev 
6049e08aacStbbdev 
6149e08aacStbbdev         std::size_t iter_on_operation = 1000;
6249e08aacStbbdev         std::size_t operation_number = std::size_t(notification_types::notify_number) * iter_on_operation;
6349e08aacStbbdev 
__anon1eb8c3140102null648b6f831cStbbdev         auto thread_func = [&, operation_number] {
6549e08aacStbbdev             for (std::size_t i = 0; i < operation_number; ++i) {
668dcbd5b1Stbbdev                 tbb::detail::r1::concurrent_monitor::thread_context context{std::uintptr_t(1)};
678dcbd5b1Stbbdev                 test_monitor.prepare_wait(context);
6849e08aacStbbdev                 barrier.wait();
6949e08aacStbbdev                 test_monitor.cancel_wait(context);
7049e08aacStbbdev             }
7149e08aacStbbdev         };
7249e08aacStbbdev 
7349e08aacStbbdev         for (std::size_t i = 0; i < threads_number - 1; ++i) {
7449e08aacStbbdev             arena.enqueue(thread_func);
7549e08aacStbbdev         }
7649e08aacStbbdev 
7749e08aacStbbdev         for (std::size_t i = 0; i < operation_number; ++i) {
7849e08aacStbbdev             barrier.wait();
7949e08aacStbbdev             switch (i / iter_on_operation) {
8049e08aacStbbdev                 case 0:
8149e08aacStbbdev                 {
__anon1eb8c3140202( std::uintptr_t ) 8249e08aacStbbdev                     test_monitor.notify([] ( std::uintptr_t ) { return true; });
8349e08aacStbbdev                     break;
8449e08aacStbbdev                 }
8549e08aacStbbdev                 case 1:
8649e08aacStbbdev                 {
8749e08aacStbbdev                     test_monitor.notify_one();
8849e08aacStbbdev                     break;
8949e08aacStbbdev                 }
9049e08aacStbbdev                 case 2:
9149e08aacStbbdev                 {
9249e08aacStbbdev                     test_monitor.notify_all();
9349e08aacStbbdev                     break;
9449e08aacStbbdev                 }
9549e08aacStbbdev             };
9649e08aacStbbdev         }
9749e08aacStbbdev     }
9849e08aacStbbdev 
9949e08aacStbbdev     tbb::finalize(handler);
10049e08aacStbbdev }
10149e08aacStbbdev #endif // TBB_USE_EXCEPTIONS
102