1 /*
2  * Copyright (C) 2017 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 HWUI_THREADBASE_H
18 #define HWUI_THREADBASE_H
19 
20 #include "WorkQueue.h"
21 #include "utils/Macros.h"
22 
23 #include <utils/Looper.h>
24 #include <utils/Thread.h>
25 
26 #include <algorithm>
27 
28 namespace android::uirenderer {
29 
30 class ThreadBase : protected Thread {
31     PREVENT_COPY_AND_ASSIGN(ThreadBase);
32 
33 public:
ThreadBase()34     ThreadBase()
35             : Thread(false)
36             , mLooper(new Looper(false))
37             , mQueue([this]() { mLooper->wake(); }, mLock) {}
38 
queue()39     WorkQueue& queue() { return mQueue; }
40 
requestExit()41     void requestExit() {
42         Thread::requestExit();
43         mLooper->wake();
44     }
45 
46     void start(const char* name = "ThreadBase") { Thread::run(name); }
47 
join()48     void join() { Thread::join(); }
49 
50 protected:
waitForWork()51     void waitForWork() {
52         nsecs_t nextWakeup;
53         {
54             std::unique_lock lock{mLock};
55             nextWakeup = mQueue.nextWakeup(lock);
56         }
57         int timeout = -1;
58         if (nextWakeup < std::numeric_limits<nsecs_t>::max()) {
59             timeout = ns2ms(nextWakeup - WorkQueue::clock::now());
60             if (timeout < 0) timeout = 0;
61         }
62         int result = mLooper->pollOnce(timeout);
63         LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR, "RenderThread Looper POLL_ERROR!");
64     }
65 
processQueue()66     void processQueue() { mQueue.process(); }
67 
threadLoop()68     virtual bool threadLoop() override {
69         while (!exitPending()) {
70             waitForWork();
71             processQueue();
72         }
73         return false;
74     }
75 
76     sp<Looper> mLooper;
77 
78 private:
79     WorkQueue mQueue;
80     std::mutex mLock;
81 };
82 
83 }  // namespace android::uirenderer
84 
85 #endif  // HWUI_THREADBASE_H
86