blob: 0c025b4f0ee7da78a3d605a64535ea1c6a2f3dc0 [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#ifndef FRAMEWORKS_BASE_COMMONPOOL_H
18#define FRAMEWORKS_BASE_COMMONPOOL_H
19
John Reck322b8ab2019-03-14 13:15:28 -070020#include <log/log.h>
21
22#include <condition_variable>
23#include <functional>
24#include <future>
25#include <mutex>
Bo Liu027b2182021-03-18 16:50:38 -040026#include <vector>
John Reck322b8ab2019-03-14 13:15:28 -070027
Jerome Gaillard9b2b7622024-03-14 18:55:30 +000028#include "thread/CommonPoolBase.h"
29#include "utils/Macros.h"
30
John Reck322b8ab2019-03-14 13:15:28 -070031namespace android {
32namespace uirenderer {
33
34template <class T, int SIZE>
35class ArrayQueue {
36 PREVENT_COPY_AND_ASSIGN(ArrayQueue);
37 static_assert(SIZE > 0, "Size must be positive");
38
39public:
40 ArrayQueue() = default;
41 ~ArrayQueue() = default;
42
43 constexpr size_t capacity() const { return SIZE; }
44 constexpr bool hasWork() const { return mHead != mTail; }
45 constexpr bool hasSpace() const { return ((mHead + 1) % SIZE) != mTail; }
46 constexpr int size() const {
47 if (mHead > mTail) {
48 return mHead - mTail;
49 } else {
50 return mTail - mHead + SIZE;
51 }
52 }
53
54 constexpr void push(T&& t) {
55 int newHead = (mHead + 1) % SIZE;
56 LOG_ALWAYS_FATAL_IF(newHead == mTail, "no space");
57
58 mBuffer[mHead] = std::move(t);
59 mHead = newHead;
60 }
61
John Reckcfd929d2019-04-08 11:28:15 -070062 constexpr T pop() {
John Reck322b8ab2019-03-14 13:15:28 -070063 LOG_ALWAYS_FATAL_IF(mTail == mHead, "empty");
64 int index = mTail;
65 mTail = (mTail + 1) % SIZE;
John Reckcfd929d2019-04-08 11:28:15 -070066 T ret = std::move(mBuffer[index]);
67 mBuffer[index] = nullptr;
68 return ret;
John Reck322b8ab2019-03-14 13:15:28 -070069 }
70
71private:
72 T mBuffer[SIZE];
73 int mHead = 0;
74 int mTail = 0;
75};
76
Jerome Gaillard9b2b7622024-03-14 18:55:30 +000077class CommonPool : private CommonPoolBase {
John Reck322b8ab2019-03-14 13:15:28 -070078 PREVENT_COPY_AND_ASSIGN(CommonPool);
79
80public:
81 using Task = std::function<void()>;
82 static constexpr auto THREAD_COUNT = 2;
83 static constexpr auto QUEUE_SIZE = 128;
84
85 static void post(Task&& func);
86
87 template <class F>
88 static auto async(F&& func) -> std::future<decltype(func())> {
89 typedef std::packaged_task<decltype(func())()> task_t;
90 auto task = std::make_shared<task_t>(std::forward<F>(func));
91 post([task]() { std::invoke(*task); });
92 return task->get_future();
93 }
94
95 template <class F>
96 static auto runSync(F&& func) -> decltype(func()) {
97 std::packaged_task<decltype(func())()> task{std::forward<F>(func)};
98 post([&task]() { std::invoke(task); });
99 return task.get_future().get();
100 };
101
Bo Liu027b2182021-03-18 16:50:38 -0400102 static std::vector<int> getThreadIds();
103
John Reckcfd929d2019-04-08 11:28:15 -0700104 // For testing purposes only, blocks until all worker threads are parked.
105 static void waitForIdle();
106
John Reck322b8ab2019-03-14 13:15:28 -0700107private:
John Reckcfd929d2019-04-08 11:28:15 -0700108 static CommonPool& instance();
109
John Reck322b8ab2019-03-14 13:15:28 -0700110 CommonPool();
Jerome Gaillard9b2b7622024-03-14 18:55:30 +0000111 ~CommonPool() {
112 mIsStopping = true;
113 mCondition.notify_all();
114 }
John Reck322b8ab2019-03-14 13:15:28 -0700115
116 void enqueue(Task&&);
John Reckcfd929d2019-04-08 11:28:15 -0700117 void doWaitForIdle();
John Reck322b8ab2019-03-14 13:15:28 -0700118
119 void workerLoop();
120
Bo Liu027b2182021-03-18 16:50:38 -0400121 std::vector<int> mWorkerThreadIds;
122
John Reck322b8ab2019-03-14 13:15:28 -0700123 std::mutex mLock;
124 std::condition_variable mCondition;
125 int mWaitingThreads = 0;
126 ArrayQueue<Task, QUEUE_SIZE> mWorkQueue;
Jerome Gaillard9b2b7622024-03-14 18:55:30 +0000127 std::atomic_bool mIsStopping = false;
John Reck322b8ab2019-03-14 13:15:28 -0700128};
129
130} // namespace uirenderer
131} // namespace android
132
133#endif // FRAMEWORKS_BASE_COMMONPOOL_H