1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker #ifndef FRAMEWORKS_BASE_COMMONPOOL_H 18*d57664e9SAndroid Build Coastguard Worker #define FRAMEWORKS_BASE_COMMONPOOL_H 19*d57664e9SAndroid Build Coastguard Worker 20*d57664e9SAndroid Build Coastguard Worker #include <log/log.h> 21*d57664e9SAndroid Build Coastguard Worker 22*d57664e9SAndroid Build Coastguard Worker #include <condition_variable> 23*d57664e9SAndroid Build Coastguard Worker #include <functional> 24*d57664e9SAndroid Build Coastguard Worker #include <future> 25*d57664e9SAndroid Build Coastguard Worker #include <mutex> 26*d57664e9SAndroid Build Coastguard Worker #include <vector> 27*d57664e9SAndroid Build Coastguard Worker 28*d57664e9SAndroid Build Coastguard Worker #include "thread/CommonPoolBase.h" 29*d57664e9SAndroid Build Coastguard Worker #include "utils/Macros.h" 30*d57664e9SAndroid Build Coastguard Worker 31*d57664e9SAndroid Build Coastguard Worker namespace android { 32*d57664e9SAndroid Build Coastguard Worker namespace uirenderer { 33*d57664e9SAndroid Build Coastguard Worker 34*d57664e9SAndroid Build Coastguard Worker template <class T, int SIZE> 35*d57664e9SAndroid Build Coastguard Worker class ArrayQueue { 36*d57664e9SAndroid Build Coastguard Worker PREVENT_COPY_AND_ASSIGN(ArrayQueue); 37*d57664e9SAndroid Build Coastguard Worker static_assert(SIZE > 0, "Size must be positive"); 38*d57664e9SAndroid Build Coastguard Worker 39*d57664e9SAndroid Build Coastguard Worker public: 40*d57664e9SAndroid Build Coastguard Worker ArrayQueue() = default; 41*d57664e9SAndroid Build Coastguard Worker ~ArrayQueue() = default; 42*d57664e9SAndroid Build Coastguard Worker capacity()43*d57664e9SAndroid Build Coastguard Worker constexpr size_t capacity() const { return SIZE; } hasWork()44*d57664e9SAndroid Build Coastguard Worker constexpr bool hasWork() const { return mHead != mTail; } hasSpace()45*d57664e9SAndroid Build Coastguard Worker constexpr bool hasSpace() const { return ((mHead + 1) % SIZE) != mTail; } size()46*d57664e9SAndroid Build Coastguard Worker constexpr int size() const { 47*d57664e9SAndroid Build Coastguard Worker if (mHead > mTail) { 48*d57664e9SAndroid Build Coastguard Worker return mHead - mTail; 49*d57664e9SAndroid Build Coastguard Worker } else { 50*d57664e9SAndroid Build Coastguard Worker return mTail - mHead + SIZE; 51*d57664e9SAndroid Build Coastguard Worker } 52*d57664e9SAndroid Build Coastguard Worker } 53*d57664e9SAndroid Build Coastguard Worker push(T && t)54*d57664e9SAndroid Build Coastguard Worker constexpr void push(T&& t) { 55*d57664e9SAndroid Build Coastguard Worker int newHead = (mHead + 1) % SIZE; 56*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(newHead == mTail, "no space"); 57*d57664e9SAndroid Build Coastguard Worker 58*d57664e9SAndroid Build Coastguard Worker mBuffer[mHead] = std::move(t); 59*d57664e9SAndroid Build Coastguard Worker mHead = newHead; 60*d57664e9SAndroid Build Coastguard Worker } 61*d57664e9SAndroid Build Coastguard Worker pop()62*d57664e9SAndroid Build Coastguard Worker constexpr T pop() { 63*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mTail == mHead, "empty"); 64*d57664e9SAndroid Build Coastguard Worker int index = mTail; 65*d57664e9SAndroid Build Coastguard Worker mTail = (mTail + 1) % SIZE; 66*d57664e9SAndroid Build Coastguard Worker T ret = std::move(mBuffer[index]); 67*d57664e9SAndroid Build Coastguard Worker mBuffer[index] = nullptr; 68*d57664e9SAndroid Build Coastguard Worker return ret; 69*d57664e9SAndroid Build Coastguard Worker } 70*d57664e9SAndroid Build Coastguard Worker 71*d57664e9SAndroid Build Coastguard Worker private: 72*d57664e9SAndroid Build Coastguard Worker T mBuffer[SIZE]; 73*d57664e9SAndroid Build Coastguard Worker int mHead = 0; 74*d57664e9SAndroid Build Coastguard Worker int mTail = 0; 75*d57664e9SAndroid Build Coastguard Worker }; 76*d57664e9SAndroid Build Coastguard Worker 77*d57664e9SAndroid Build Coastguard Worker class CommonPool : private CommonPoolBase { 78*d57664e9SAndroid Build Coastguard Worker PREVENT_COPY_AND_ASSIGN(CommonPool); 79*d57664e9SAndroid Build Coastguard Worker 80*d57664e9SAndroid Build Coastguard Worker public: 81*d57664e9SAndroid Build Coastguard Worker using Task = std::function<void()>; 82*d57664e9SAndroid Build Coastguard Worker static constexpr auto THREAD_COUNT = 2; 83*d57664e9SAndroid Build Coastguard Worker static constexpr auto QUEUE_SIZE = 128; 84*d57664e9SAndroid Build Coastguard Worker 85*d57664e9SAndroid Build Coastguard Worker static void post(Task&& func); 86*d57664e9SAndroid Build Coastguard Worker 87*d57664e9SAndroid Build Coastguard Worker template <class F> 88*d57664e9SAndroid Build Coastguard Worker static auto async(F&& func) -> std::future<decltype(func())> { 89*d57664e9SAndroid Build Coastguard Worker typedef std::packaged_task<decltype(func())()> task_t; 90*d57664e9SAndroid Build Coastguard Worker auto task = std::make_shared<task_t>(std::forward<F>(func)); 91*d57664e9SAndroid Build Coastguard Worker post([task]() { std::invoke(*task); }); 92*d57664e9SAndroid Build Coastguard Worker return task->get_future(); 93*d57664e9SAndroid Build Coastguard Worker } 94*d57664e9SAndroid Build Coastguard Worker 95*d57664e9SAndroid Build Coastguard Worker template <class F> 96*d57664e9SAndroid Build Coastguard Worker static auto runSync(F&& func) -> decltype(func()) { 97*d57664e9SAndroid Build Coastguard Worker std::packaged_task<decltype(func())()> task{std::forward<F>(func)}; 98*d57664e9SAndroid Build Coastguard Worker post([&task]() { std::invoke(task); }); 99*d57664e9SAndroid Build Coastguard Worker return task.get_future().get(); 100*d57664e9SAndroid Build Coastguard Worker }; 101*d57664e9SAndroid Build Coastguard Worker 102*d57664e9SAndroid Build Coastguard Worker static std::vector<int> getThreadIds(); 103*d57664e9SAndroid Build Coastguard Worker 104*d57664e9SAndroid Build Coastguard Worker // For testing purposes only, blocks until all worker threads are parked. 105*d57664e9SAndroid Build Coastguard Worker static void waitForIdle(); 106*d57664e9SAndroid Build Coastguard Worker 107*d57664e9SAndroid Build Coastguard Worker private: 108*d57664e9SAndroid Build Coastguard Worker static CommonPool& instance(); 109*d57664e9SAndroid Build Coastguard Worker 110*d57664e9SAndroid Build Coastguard Worker CommonPool(); ~CommonPool()111*d57664e9SAndroid Build Coastguard Worker ~CommonPool() { 112*d57664e9SAndroid Build Coastguard Worker mIsStopping = true; 113*d57664e9SAndroid Build Coastguard Worker mCondition.notify_all(); 114*d57664e9SAndroid Build Coastguard Worker } 115*d57664e9SAndroid Build Coastguard Worker 116*d57664e9SAndroid Build Coastguard Worker void enqueue(Task&&); 117*d57664e9SAndroid Build Coastguard Worker void doWaitForIdle(); 118*d57664e9SAndroid Build Coastguard Worker 119*d57664e9SAndroid Build Coastguard Worker void workerLoop(); 120*d57664e9SAndroid Build Coastguard Worker 121*d57664e9SAndroid Build Coastguard Worker std::vector<int> mWorkerThreadIds; 122*d57664e9SAndroid Build Coastguard Worker 123*d57664e9SAndroid Build Coastguard Worker std::mutex mLock; 124*d57664e9SAndroid Build Coastguard Worker std::condition_variable mCondition; 125*d57664e9SAndroid Build Coastguard Worker int mWaitingThreads = 0; 126*d57664e9SAndroid Build Coastguard Worker ArrayQueue<Task, QUEUE_SIZE> mWorkQueue; 127*d57664e9SAndroid Build Coastguard Worker std::atomic_bool mIsStopping = false; 128*d57664e9SAndroid Build Coastguard Worker }; 129*d57664e9SAndroid Build Coastguard Worker 130*d57664e9SAndroid Build Coastguard Worker } // namespace uirenderer 131*d57664e9SAndroid Build Coastguard Worker } // namespace android 132*d57664e9SAndroid Build Coastguard Worker 133*d57664e9SAndroid Build Coastguard Worker #endif // FRAMEWORKS_BASE_COMMONPOOL_H 134