/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HWUI_THREADBASE_H #define HWUI_THREADBASE_H #include "WorkQueue.h" #include "utils/Macros.h" #include <utils/Looper.h> #include <utils/Thread.h> #include <algorithm> namespace android::uirenderer { class ThreadBase : public Thread { PREVENT_COPY_AND_ASSIGN(ThreadBase); public: ThreadBase() : Thread(false) , mLooper(new Looper(false)) , mQueue([this]() { mLooper->wake(); }, mLock) {} WorkQueue& queue() { return mQueue; } void requestExit() { Thread::requestExit(); mLooper->wake(); } void start(const char* name = "ThreadBase") { Thread::run(name); } void join() { Thread::join(); } bool isRunning() const { return Thread::isRunning(); } protected: void waitForWork() { nsecs_t nextWakeup; { std::unique_lock lock{mLock}; nextWakeup = mQueue.nextWakeup(lock); } int timeout = -1; if (nextWakeup < std::numeric_limits<nsecs_t>::max()) { timeout = ns2ms(nextWakeup - WorkQueue::clock::now()); if (timeout < 0) timeout = 0; } int result = mLooper->pollOnce(timeout); LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR, "RenderThread Looper POLL_ERROR!"); } void processQueue() { mQueue.process(); } virtual bool threadLoop() override { Looper::setForThread(mLooper); while (!exitPending()) { waitForWork(); processQueue(); } Looper::setForThread(nullptr); return false; } sp<Looper> mLooper; private: WorkQueue mQueue; std::mutex mLock; }; } // namespace android::uirenderer #endif // HWUI_THREADBASE_H