blob: bf1530022743ee8f13a33e0794d5c9ac798aeb35 [file] [log] [blame]
Ana Krulec70d15b1b2020-12-01 10:05:15 -08001/*
2 * Copyright 2020 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 "CommonPool.h"
18
19#undef LOG_TAG
20#define LOG_TAG "RenderEngine"
21#define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
23#include <sys/resource.h>
24#include <utils/Trace.h>
25
26#include <system/thread_defs.h>
27#include <array>
28
29namespace android {
30namespace renderengine {
31namespace skia {
32
33CommonPool::CommonPool() {
34 ATRACE_CALL();
35
36 CommonPool* pool = this;
37 // Create 2 workers
38 for (int i = 0; i < THREAD_COUNT; i++) {
39 std::thread worker([pool, i] {
40 {
41 std::array<char, 20> name{"reTask"};
42 snprintf(name.data(), name.size(), "reTask%d", i);
43 auto self = pthread_self();
44 pthread_setname_np(self, name.data());
45 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND);
46 }
47 pool->workerLoop();
48 });
49 worker.detach();
50 }
51}
52
53CommonPool& CommonPool::instance() {
54 static CommonPool pool;
55 return pool;
56}
57
58void CommonPool::post(Task&& task) {
59 instance().enqueue(std::move(task));
60}
61
62void CommonPool::enqueue(Task&& task) {
63 std::unique_lock lock(mLock);
64 while (mWorkQueue.size() > QUEUE_SIZE) {
65 lock.unlock();
66 ALOGW("Queue is full: %d, waiting before adding more tasks.", QUEUE_SIZE);
67 usleep(100);
68 lock.lock();
69 }
70 mWorkQueue.push(std::move(task));
71 if (mWaitingThreads == THREAD_COUNT || (mWaitingThreads > 0 && mWorkQueue.size() > 1)) {
72 mCondition.notify_one();
73 }
74}
75
76void CommonPool::workerLoop() {
77 std::unique_lock lock(mLock);
78 while (true) {
79 if (mWorkQueue.size() == 0) {
80 mWaitingThreads++;
81 mCondition.wait(lock);
82 mWaitingThreads--;
83 }
84 // Need to double-check that work is still available now that we have the lock
85 // It may have already been grabbed by a different thread
86 while (mWorkQueue.size() > 0) {
87 auto work = mWorkQueue.front();
88 mWorkQueue.pop();
89 lock.unlock();
90 work();
91 lock.lock();
92 }
93 }
94}
95
96} // namespace skia
97} // namespace renderengine
98} // namespace android