| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // This file is part of OpenCV project.
- // It is subject to the license terms in the LICENSE file found in the top-level directory
- // of this distribution and at http://opencv.org/license.html.
- //
- // Copyright (C) 2024 Intel Corporation
- #include "../test_precomp.hpp"
- #include <chrono>
- #include <thread>
- #include "executor/thread_pool.hpp"
- namespace opencv_test
- {
- using namespace cv::gapi;
- TEST(ThreadPool, ScheduleNotBlock)
- {
- own::Latch latch(1u);
- std::atomic<uint32_t> counter{0u};
- own::ThreadPool tp(4u);
- tp.schedule([&](){
- std::this_thread::sleep_for(std::chrono::milliseconds{500u});
- counter++;
- latch.count_down();
- });
- EXPECT_EQ(0u, counter);
- latch.wait();
- EXPECT_EQ(1u, counter);
- }
- TEST(ThreadPool, MultipleTasks)
- {
- const uint32_t kNumTasks = 100u;
- own::Latch latch(kNumTasks);
- std::atomic<uint32_t> completed{0u};
- own::ThreadPool tp(4u);
- for (uint32_t i = 0; i < kNumTasks; ++i) {
- tp.schedule([&]() {
- ++completed;
- latch.count_down();
- });
- }
- latch.wait();
- EXPECT_EQ(kNumTasks, completed.load());
- }
- struct ExecutionState {
- ExecutionState(const uint32_t num_threads,
- const uint32_t num_tasks)
- : guard(0u),
- critical(0u),
- limit(num_tasks),
- latch(num_threads),
- tp(num_threads) {
- }
- std::atomic<uint32_t> guard;
- std::atomic<uint32_t> critical;
- const uint32_t limit;
- own::Latch latch;
- own::ThreadPool tp;
- };
- static void doRecursive(ExecutionState& state) {
- // NB: Protects function to be executed no more than limit number of times
- if (state.guard.fetch_add(1u) >= state.limit) {
- state.latch.count_down();
- return;
- }
- // NB: This simulates critical section
- std::this_thread::sleep_for(std::chrono::milliseconds{50});
- ++state.critical;
- // NB: Schedule the new one recursively
- state.tp.schedule([&](){ doRecursive(state); });
- }
- TEST(ThreadPool, ScheduleRecursively)
- {
- const int kNumThreads = 5u;
- const uint32_t kNumTasks = 100u;
- ExecutionState state(kNumThreads, kNumTasks);
- for (uint32_t i = 0; i < kNumThreads; ++i) {
- state.tp.schedule([&](){
- doRecursive(state);
- });
- }
- state.latch.wait();
- EXPECT_EQ(kNumTasks, state.critical.load());
- }
- TEST(ThreadPool, ExecutionIsParallel)
- {
- const uint32_t kNumThreads = 4u;
- std::atomic<uint32_t> counter{0};
- own::Latch latch{kNumThreads};
- own::ThreadPool tp(kNumThreads);
- auto start = std::chrono::high_resolution_clock::now();
- for (uint32_t i = 0; i < kNumThreads; ++i) {
- tp.schedule([&]() {
- std::this_thread::sleep_for(std::chrono::milliseconds{800u});
- ++counter;
- latch.count_down();
- });
- }
- latch.wait();
- auto end = std::chrono::high_resolution_clock::now();
- auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
- EXPECT_GE(1000u, elapsed);
- EXPECT_EQ(kNumThreads, counter.load());
- }
- } // namespace opencv_test
|