1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2013 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker #ifndef RENDERTASK_H_ 18*d57664e9SAndroid Build Coastguard Worker #define RENDERTASK_H_ 19*d57664e9SAndroid Build Coastguard Worker 20*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h> 21*d57664e9SAndroid Build Coastguard Worker #include <utils/Timers.h> 22*d57664e9SAndroid Build Coastguard Worker 23*d57664e9SAndroid Build Coastguard Worker namespace android { 24*d57664e9SAndroid Build Coastguard Worker class Mutex; 25*d57664e9SAndroid Build Coastguard Worker class Condition; 26*d57664e9SAndroid Build Coastguard Worker namespace uirenderer { 27*d57664e9SAndroid Build Coastguard Worker namespace renderthread { 28*d57664e9SAndroid Build Coastguard Worker 29*d57664e9SAndroid Build Coastguard Worker #define METHOD_INVOKE_PAYLOAD_SIZE (8 * sizeof(void*)) 30*d57664e9SAndroid Build Coastguard Worker 31*d57664e9SAndroid Build Coastguard Worker /* 32*d57664e9SAndroid Build Coastguard Worker * Notes about memory management 33*d57664e9SAndroid Build Coastguard Worker * 34*d57664e9SAndroid Build Coastguard Worker * RenderThread will only invoke RenderTask::run(). It is the responsibility 35*d57664e9SAndroid Build Coastguard Worker * of the RenderTask to know if it needs to suicide at the end of run() or 36*d57664e9SAndroid Build Coastguard Worker * if some other lifecycle is being used. As such, it is not valid to reference 37*d57664e9SAndroid Build Coastguard Worker * anything on RenderTask after the first call to run(). 38*d57664e9SAndroid Build Coastguard Worker * 39*d57664e9SAndroid Build Coastguard Worker * For example SignalingRenderTask 40*d57664e9SAndroid Build Coastguard Worker * is expected to be stack allocated by the calling thread, so it does not 41*d57664e9SAndroid Build Coastguard Worker * suicide in run() but instead relies on the caller to destroy it. 42*d57664e9SAndroid Build Coastguard Worker * 43*d57664e9SAndroid Build Coastguard Worker * MethodInvokeRenderTask however is currently allocated with new, so it will 44*d57664e9SAndroid Build Coastguard Worker * suicide at the end of run(). TODO: Replace this with a small pool to avoid 45*d57664e9SAndroid Build Coastguard Worker * malloc/free churn of small objects? 46*d57664e9SAndroid Build Coastguard Worker */ 47*d57664e9SAndroid Build Coastguard Worker 48*d57664e9SAndroid Build Coastguard Worker class RenderTask { 49*d57664e9SAndroid Build Coastguard Worker public: RenderTask()50*d57664e9SAndroid Build Coastguard Worker RenderTask() : mNext(nullptr), mRunAt(0) {} ~RenderTask()51*d57664e9SAndroid Build Coastguard Worker virtual ~RenderTask() {} 52*d57664e9SAndroid Build Coastguard Worker 53*d57664e9SAndroid Build Coastguard Worker virtual void run() = 0; 54*d57664e9SAndroid Build Coastguard Worker 55*d57664e9SAndroid Build Coastguard Worker RenderTask* mNext; 56*d57664e9SAndroid Build Coastguard Worker nsecs_t mRunAt; // nano-seconds on the SYSTEM_TIME_MONOTONIC clock 57*d57664e9SAndroid Build Coastguard Worker }; 58*d57664e9SAndroid Build Coastguard Worker 59*d57664e9SAndroid Build Coastguard Worker class SignalingRenderTask : public RenderTask { 60*d57664e9SAndroid Build Coastguard Worker public: 61*d57664e9SAndroid Build Coastguard Worker // Takes ownership of task, caller owns lock and signal SignalingRenderTask(RenderTask * task,Mutex * lock,Condition * signal)62*d57664e9SAndroid Build Coastguard Worker SignalingRenderTask(RenderTask* task, Mutex* lock, Condition* signal) 63*d57664e9SAndroid Build Coastguard Worker : mTask(task), mLock(lock), mSignal(signal), mHasRun(false) {} 64*d57664e9SAndroid Build Coastguard Worker virtual void run() override; hasRun()65*d57664e9SAndroid Build Coastguard Worker bool hasRun() const { return mHasRun; } 66*d57664e9SAndroid Build Coastguard Worker 67*d57664e9SAndroid Build Coastguard Worker private: 68*d57664e9SAndroid Build Coastguard Worker RenderTask* mTask; 69*d57664e9SAndroid Build Coastguard Worker Mutex* mLock; 70*d57664e9SAndroid Build Coastguard Worker Condition* mSignal; 71*d57664e9SAndroid Build Coastguard Worker bool mHasRun; 72*d57664e9SAndroid Build Coastguard Worker }; 73*d57664e9SAndroid Build Coastguard Worker 74*d57664e9SAndroid Build Coastguard Worker typedef void* (*RunnableMethod)(void* data); 75*d57664e9SAndroid Build Coastguard Worker 76*d57664e9SAndroid Build Coastguard Worker class MethodInvokeRenderTask : public RenderTask { 77*d57664e9SAndroid Build Coastguard Worker public: MethodInvokeRenderTask(RunnableMethod method)78*d57664e9SAndroid Build Coastguard Worker explicit MethodInvokeRenderTask(RunnableMethod method) : mMethod(method), mReturnPtr(nullptr) {} 79*d57664e9SAndroid Build Coastguard Worker payload()80*d57664e9SAndroid Build Coastguard Worker void* payload() { return mData; } setReturnPtr(void ** retptr)81*d57664e9SAndroid Build Coastguard Worker void setReturnPtr(void** retptr) { mReturnPtr = retptr; } 82*d57664e9SAndroid Build Coastguard Worker run()83*d57664e9SAndroid Build Coastguard Worker virtual void run() override { 84*d57664e9SAndroid Build Coastguard Worker void* retval = mMethod(mData); 85*d57664e9SAndroid Build Coastguard Worker if (mReturnPtr) { 86*d57664e9SAndroid Build Coastguard Worker *mReturnPtr = retval; 87*d57664e9SAndroid Build Coastguard Worker } 88*d57664e9SAndroid Build Coastguard Worker // Commit suicide 89*d57664e9SAndroid Build Coastguard Worker delete this; 90*d57664e9SAndroid Build Coastguard Worker } 91*d57664e9SAndroid Build Coastguard Worker 92*d57664e9SAndroid Build Coastguard Worker private: 93*d57664e9SAndroid Build Coastguard Worker RunnableMethod mMethod; 94*d57664e9SAndroid Build Coastguard Worker char mData[METHOD_INVOKE_PAYLOAD_SIZE]; 95*d57664e9SAndroid Build Coastguard Worker void** mReturnPtr; 96*d57664e9SAndroid Build Coastguard Worker }; 97*d57664e9SAndroid Build Coastguard Worker 98*d57664e9SAndroid Build Coastguard Worker } /* namespace renderthread */ 99*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */ 100*d57664e9SAndroid Build Coastguard Worker } /* namespace android */ 101*d57664e9SAndroid Build Coastguard Worker #endif /* RENDERTASK_H_ */ 102