xref: /aosp_15_r20/external/perfetto/src/base/threading/thread_pool_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
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 "perfetto/ext/base/threading/thread_pool.h"
18 #include <atomic>
19 #include <condition_variable>
20 #include <mutex>
21 
22 #include "perfetto/ext/base/waitable_event.h"
23 #include "test/gtest_and_gmock.h"
24 
25 namespace perfetto {
26 namespace base {
27 namespace {
28 
29 struct ThreadLatch {
30   base::WaitableEvent notify;
31   base::WaitableEvent wait;
32   bool task_started = false;
33 };
34 
TEST(ThreadPoolTest,SequentialQueueing)35 TEST(ThreadPoolTest, SequentialQueueing) {
36   ThreadLatch first;
37   ThreadLatch second;
38   base::ThreadPool pool(1);
39 
40   pool.PostTask([&first] {
41     first.task_started = true;
42     first.notify.Notify();
43     first.wait.Wait();
44   });
45 
46   pool.PostTask([&second] {
47     second.task_started = true;
48     second.notify.Notify();
49     second.wait.Wait();
50   });
51 
52   first.notify.Wait();
53   ASSERT_TRUE(first.task_started);
54   ASSERT_FALSE(second.task_started);
55   first.wait.Notify();
56 
57   second.notify.Wait();
58   ASSERT_TRUE(second.task_started);
59   second.wait.Notify();
60 }
61 
TEST(ThreadPoolTest,ParallelSecondFinishFirst)62 TEST(ThreadPoolTest, ParallelSecondFinishFirst) {
63   base::ThreadPool pool(2);
64 
65   ThreadLatch first;
66   pool.PostTask([&first] {
67     first.wait.Wait();
68     first.task_started = true;
69     first.notify.Notify();
70   });
71 
72   ThreadLatch second;
73   pool.PostTask([&second] {
74     second.wait.Wait();
75     second.task_started = true;
76     second.notify.Notify();
77   });
78 
79   second.wait.Notify();
80   second.notify.Wait();
81   ASSERT_TRUE(second.task_started);
82 
83   first.wait.Notify();
84   first.notify.Wait();
85   ASSERT_TRUE(first.task_started);
86 }
87 
TEST(ThreadPoolTest,StressTest)88 TEST(ThreadPoolTest, StressTest) {
89   std::mutex mu;
90   std::condition_variable cv;
91   uint32_t count = 0;
92   base::ThreadPool pool(128);
93   for (uint32_t i = 0; i < 1024; ++i) {
94     pool.PostTask([&mu, &count, &cv] {
95       std::lock_guard<std::mutex> guard(mu);
96       if (++count == 1024) {
97         cv.notify_one();
98       }
99     });
100   }
101 
102   std::unique_lock<std::mutex> lock(mu);
103   cv.wait(lock, [&count]() { return count == 1024u; });
104 }
105 
106 }  // namespace
107 }  // namespace base
108 }  // namespace perfetto
109