blob: 51628259d2a8c57cd4e78bbdccbfd7a5c99bbd0b [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
20#include "utils/Macros.h"
21
22#include <log/log.h>
23
24#include <condition_variable>
25#include <functional>
26#include <future>
27#include <mutex>
28
29namespace android {
30namespace uirenderer {
31
32template <class T, int SIZE>
33class ArrayQueue {
34 PREVENT_COPY_AND_ASSIGN(ArrayQueue);
35 static_assert(SIZE > 0, "Size must be positive");
36
37public:
38 ArrayQueue() = default;
39 ~ArrayQueue() = default;
40
41 constexpr size_t capacity() const { return SIZE; }
42 constexpr bool hasWork() const { return mHead != mTail; }
43 constexpr bool hasSpace() const { return ((mHead + 1) % SIZE) != mTail; }
44 constexpr int size() const {
45 if (mHead > mTail) {
46 return mHead - mTail;
47 } else {
48 return mTail - mHead + SIZE;
49 }
50 }
51
52 constexpr void push(T&& t) {
53 int newHead = (mHead + 1) % SIZE;
54 LOG_ALWAYS_FATAL_IF(newHead == mTail, "no space");
55
56 mBuffer[mHead] = std::move(t);
57 mHead = newHead;
58 }
59
John Reck5ff61f32019-04-04 15:49:40 -070060 constexpr T pop() {
John Reck322b8ab2019-03-14 13:15:28 -070061 LOG_ALWAYS_FATAL_IF(mTail == mHead, "empty");
62 int index = mTail;
63 mTail = (mTail + 1) % SIZE;
John Reck5ff61f32019-04-04 15:49:40 -070064 T ret = std::move(mBuffer[index]);
65 mBuffer[index] = nullptr;
66 return ret;
John Reck322b8ab2019-03-14 13:15:28 -070067 }
68
69private:
70 T mBuffer[SIZE];
71 int mHead = 0;
72 int mTail = 0;
73};
74
75class CommonPool {
76 PREVENT_COPY_AND_ASSIGN(CommonPool);
77
78public:
79 using Task = std::function<void()>;
80 static constexpr auto THREAD_COUNT = 2;
81 static constexpr auto QUEUE_SIZE = 128;
82
83 static void post(Task&& func);
84
85 template <class F>
86 static auto async(F&& func) -> std::future<decltype(func())> {
87 typedef std::packaged_task<decltype(func())()> task_t;
88 auto task = std::make_shared<task_t>(std::forward<F>(func));
89 post([task]() { std::invoke(*task); });
90 return task->get_future();
91 }
92
93 template <class F>
94 static auto runSync(F&& func) -> decltype(func()) {
95 std::packaged_task<decltype(func())()> task{std::forward<F>(func)};
96 post([&task]() { std::invoke(task); });
97 return task.get_future().get();
98 };
99
100private:
101 CommonPool();
102 ~CommonPool() {}
103
104 void enqueue(Task&&);
105
106 void workerLoop();
107
108 std::mutex mLock;
109 std::condition_variable mCondition;
110 int mWaitingThreads = 0;
111 ArrayQueue<Task, QUEUE_SIZE> mWorkQueue;
112};
113
114} // namespace uirenderer
115} // namespace android
116
117#endif // FRAMEWORKS_BASE_COMMONPOOL_H