1 /* 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 27 using namespace android; 28 using namespace android::uirenderer; 29 30 TEST(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 39 // test currently relies on timings, which 40 // makes it flaky. Disable for now 41 TEST(DISABLED_CommonPool, threadCount) { 42 std::set<pid_t> threads; 43 std::array<std::future<pid_t>, 64> futures; 44 for (int i = 0; i < futures.size(); i++) { 45 futures[i] = CommonPool::async([] { 46 usleep(10); 47 return gettid(); 48 }); 49 } 50 for (auto& f : futures) { 51 threads.insert(f.get()); 52 } 53 EXPECT_EQ(threads.size(), CommonPool::THREAD_COUNT); 54 EXPECT_EQ(0, threads.count(gettid())); 55 } 56 57 TEST(CommonPool, singleThread) { 58 std::mutex mutex; 59 std::condition_variable fence; 60 bool isProcessing = false; 61 bool queuedSecond = false; 62 63 auto f1 = CommonPool::async([&] { 64 { 65 std::unique_lock lock{mutex}; 66 isProcessing = true; 67 fence.notify_all(); 68 while (!queuedSecond) { 69 fence.wait(lock); 70 } 71 } 72 return gettid(); 73 }); 74 75 { 76 std::unique_lock lock{mutex}; 77 while (!isProcessing) { 78 fence.wait(lock); 79 } 80 } 81 82 auto f2 = CommonPool::async([] { 83 return gettid(); 84 }); 85 86 { 87 std::unique_lock lock{mutex}; 88 queuedSecond = true; 89 fence.notify_all(); 90 } 91 92 auto tid1 = f1.get(); 93 auto tid2 = f2.get(); 94 EXPECT_EQ(tid1, tid2); 95 EXPECT_NE(gettid(), tid1); 96 } 97 98 // Test currently relies on timings 99 // which makes it flaky, disable for now 100 TEST(DISABLED_CommonPool, fullQueue) { 101 std::mutex lock; 102 std::condition_variable fence; 103 bool signaled = false; 104 static constexpr auto QUEUE_COUNT = CommonPool::THREAD_COUNT + CommonPool::QUEUE_SIZE + 10; 105 std::atomic_int queuedCount{0}; 106 std::array<std::future<void>, QUEUE_COUNT> futures; 107 108 std::thread queueThread{[&] { 109 for (int i = 0; i < QUEUE_COUNT; i++) { 110 futures[i] = CommonPool::async([&] { 111 std::unique_lock _lock{lock}; 112 while (!signaled) { 113 fence.wait(_lock); 114 } 115 }); 116 queuedCount++; 117 } 118 }}; 119 120 int previous; 121 do { 122 previous = queuedCount.load(); 123 usleep(10000); 124 } while (previous != queuedCount.load()); 125 126 EXPECT_GT(queuedCount.load(), CommonPool::QUEUE_SIZE); 127 EXPECT_LT(queuedCount.load(), QUEUE_COUNT); 128 129 { 130 std::unique_lock _lock{lock}; 131 signaled = true; 132 fence.notify_all(); 133 } 134 135 queueThread.join(); 136 EXPECT_EQ(queuedCount.load(), QUEUE_COUNT); 137 138 // Ensure all our tasks are finished before return as they have references to the stack 139 for (auto& f : futures) { 140 f.get(); 141 } 142 } 143 144 class ObjectTracker { 145 static std::atomic_int sGlobalCount; 146 147 public: 148 ObjectTracker() { 149 sGlobalCount++; 150 } 151 ObjectTracker(const ObjectTracker&) { 152 sGlobalCount++; 153 } 154 ObjectTracker(ObjectTracker&&) { 155 sGlobalCount++; 156 } 157 ~ObjectTracker() { 158 sGlobalCount--; 159 } 160 161 static int count() { return sGlobalCount.load(); } 162 }; 163 164 std::atomic_int ObjectTracker::sGlobalCount{0}; 165 166 TEST(CommonPool, asyncLifecycleCheck) { 167 ASSERT_EQ(0, ObjectTracker::count()); 168 { 169 ObjectTracker obj; 170 ASSERT_EQ(1, ObjectTracker::count()); 171 EXPECT_LT(1, CommonPool::async([obj] { return ObjectTracker::count(); }).get()); 172 } 173 CommonPool::waitForIdle(); 174 ASSERT_EQ(0, ObjectTracker::count()); 175 } 176 177 TEST(CommonPool, syncLifecycleCheck) { 178 ASSERT_EQ(0, ObjectTracker::count()); 179 { 180 ObjectTracker obj; 181 ASSERT_EQ(1, ObjectTracker::count()); 182 EXPECT_LT(1, CommonPool::runSync([obj] { return ObjectTracker::count(); })); 183 } 184 CommonPool::waitForIdle(); 185 ASSERT_EQ(0, ObjectTracker::count()); 186 } 187