blob: dd70258c2aa41f55baa255b86e3f23b6f937f24f [file] [log] [blame]
/*
* 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 <atomic>
#include <condition_variable>
#include <mutex>
#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<std::mutex> guard(mu);
if (++count == 1024) {
cv.notify_one();
}
});
}
std::unique_lock<std::mutex> lock(mu);
cv.wait(lock, [&count]() { return count == 1024u; });
}
} // namespace
} // namespace base
} // namespace perfetto