blob: 70a5f5acbb6ee0f2e6a83560cd370d350ae0563a [file] [log] [blame]
John Reck322b8ab2019-03-14 13:15:28 -07001/*
2 * Copyright (C) 2019 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 <gtest/gtest.h>
18
19#include "thread/CommonPool.h"
20
21#include <array>
22#include <condition_variable>
23#include <set>
24#include <thread>
25#include "unistd.h"
26
27using namespace android;
28using namespace android::uirenderer;
29
30TEST(CommonPool, post) {
31 std::atomic_bool ran(false);
32 CommonPool::post([&ran] { ran = true; });
33 for (int i = 0; !ran && i < 1000; i++) {
34 usleep(1);
35 }
36 EXPECT_TRUE(ran) << "Failed to flip atomic after 1 second";
37}
38
39TEST(CommonPool, threadCount) {
40 std::set<pid_t> threads;
41 std::array<std::future<pid_t>, 64> futures;
42 for (int i = 0; i < futures.size(); i++) {
43 futures[i] = CommonPool::async([] {
44 usleep(10);
45 return gettid();
46 });
47 }
48 for (auto& f : futures) {
49 threads.insert(f.get());
50 }
51 EXPECT_EQ(threads.size(), CommonPool::THREAD_COUNT);
52 EXPECT_EQ(0, threads.count(gettid()));
53}
54
55TEST(CommonPool, singleThread) {
56 std::mutex mutex;
57 std::condition_variable fence;
58 bool isProcessing = false;
59 bool queuedSecond = false;
60
61 auto f1 = CommonPool::async([&] {
62 {
63 std::unique_lock lock{mutex};
64 isProcessing = true;
65 fence.notify_all();
66 while (!queuedSecond) {
67 fence.wait(lock);
68 }
69 }
70 return gettid();
71 });
72
73 {
74 std::unique_lock lock{mutex};
75 while (!isProcessing) {
76 fence.wait(lock);
77 }
78 }
79
80 auto f2 = CommonPool::async([] {
81 return gettid();
82 });
83
84 {
85 std::unique_lock lock{mutex};
86 queuedSecond = true;
87 fence.notify_all();
88 }
89
90 auto tid1 = f1.get();
91 auto tid2 = f2.get();
92 EXPECT_EQ(tid1, tid2);
93 EXPECT_NE(gettid(), tid1);
94}
95
96TEST(CommonPool, fullQueue) {
97 std::mutex lock;
98 std::condition_variable fence;
99 bool signaled = false;
100 static constexpr auto QUEUE_COUNT = CommonPool::THREAD_COUNT + CommonPool::QUEUE_SIZE + 10;
101 std::atomic_int queuedCount{0};
102 std::array<std::future<void>, QUEUE_COUNT> futures;
103
104 std::thread queueThread{[&] {
105 for (int i = 0; i < QUEUE_COUNT; i++) {
106 futures[i] = CommonPool::async([&] {
107 std::unique_lock _lock{lock};
108 while (!signaled) {
109 fence.wait(_lock);
110 }
111 });
112 queuedCount++;
113 }
114 }};
115
116 int previous;
117 do {
118 previous = queuedCount.load();
119 usleep(10000);
120 } while (previous != queuedCount.load());
121
122 EXPECT_GT(queuedCount.load(), CommonPool::QUEUE_SIZE);
123 EXPECT_LT(queuedCount.load(), QUEUE_COUNT);
124
125 {
126 std::unique_lock _lock{lock};
127 signaled = true;
128 fence.notify_all();
129 }
130
131 queueThread.join();
132 EXPECT_EQ(queuedCount.load(), QUEUE_COUNT);
133
134 // Ensure all our tasks are finished before return as they have references to the stack
135 for (auto& f : futures) {
136 f.get();
137 }
John Reckcfd929d2019-04-08 11:28:15 -0700138}
139
140class ObjectTracker {
141 static std::atomic_int sGlobalCount;
142
143public:
144 ObjectTracker() {
145 sGlobalCount++;
146 }
147 ObjectTracker(const ObjectTracker&) {
148 sGlobalCount++;
149 }
150 ObjectTracker(ObjectTracker&&) {
151 sGlobalCount++;
152 }
153 ~ObjectTracker() {
154 sGlobalCount--;
155 }
156
157 static int count() { return sGlobalCount.load(); }
158};
159
160std::atomic_int ObjectTracker::sGlobalCount{0};
161
162TEST(CommonPool, asyncLifecycleCheck) {
163 ASSERT_EQ(0, ObjectTracker::count());
164 {
165 ObjectTracker obj;
166 ASSERT_EQ(1, ObjectTracker::count());
167 EXPECT_LT(1, CommonPool::async([obj] { return ObjectTracker::count(); }).get());
168 }
169 CommonPool::waitForIdle();
170 ASSERT_EQ(0, ObjectTracker::count());
171}
172
173TEST(CommonPool, syncLifecycleCheck) {
174 ASSERT_EQ(0, ObjectTracker::count());
175 {
176 ObjectTracker obj;
177 ASSERT_EQ(1, ObjectTracker::count());
178 EXPECT_LT(1, CommonPool::runSync([obj] { return ObjectTracker::count(); }));
179 }
180 CommonPool::waitForIdle();
181 ASSERT_EQ(0, ObjectTracker::count());
John Reck322b8ab2019-03-14 13:15:28 -0700182}