/* * Copyright (C) 2023 The Android Open Source Project * * 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 "perfetto/ext/base//threading/thread_pool.h" #include #include #include #include "perfetto/ext/base/waitable_event.h" #include "test/gtest_and_gmock.h" namespace perfetto { namespace base { namespace { struct ThreadLatch { base::WaitableEvent notify; base::WaitableEvent wait; bool task_started = false; }; TEST(ThreadPoolTest, SequentialQueueing) { ThreadLatch first; ThreadLatch second; base::ThreadPool pool(1); pool.PostTask([&first] { first.task_started = true; first.notify.Notify(); first.wait.Wait(); }); pool.PostTask([&second] { second.task_started = true; second.notify.Notify(); second.wait.Wait(); }); first.notify.Wait(); ASSERT_TRUE(first.task_started); ASSERT_FALSE(second.task_started); first.wait.Notify(); second.notify.Wait(); ASSERT_TRUE(second.task_started); second.wait.Notify(); } TEST(ThreadPoolTest, ParallelSecondFinishFirst) { base::ThreadPool pool(2); ThreadLatch first; pool.PostTask([&first] { first.wait.Wait(); first.task_started = true; first.notify.Notify(); }); ThreadLatch second; pool.PostTask([&second] { second.wait.Wait(); second.task_started = true; second.notify.Notify(); }); second.wait.Notify(); second.notify.Wait(); ASSERT_TRUE(second.task_started); first.wait.Notify(); first.notify.Wait(); ASSERT_TRUE(first.task_started); } TEST(ThreadPoolTest, StressTest) { std::mutex mu; std::condition_variable cv; uint32_t count = 0; base::ThreadPool pool(128); for (uint32_t i = 0; i < 1024; ++i) { pool.PostTask([&mu, &count, &cv] { std::lock_guard guard(mu); if (++count == 1024) { cv.notify_one(); } }); } std::unique_lock lock(mu); cv.wait(lock, [&count]() { return count == 1024u; }); } } // namespace } // namespace base } // namespace perfetto