Home | History | Annotate | Download | only in thread
      1 /*
      2  * Copyright (C) 2013 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 <sys/resource.h>
     18 #include <sys/sysinfo.h>
     19 
     20 #include "TaskManager.h"
     21 #include "Task.h"
     22 #include "TaskProcessor.h"
     23 #include "utils/MathUtils.h"
     24 
     25 namespace android {
     26 namespace uirenderer {
     27 
     28 ///////////////////////////////////////////////////////////////////////////////
     29 // Manager
     30 ///////////////////////////////////////////////////////////////////////////////
     31 
     32 TaskManager::TaskManager() {
     33     // Get the number of available CPUs. This value does not change over time.
     34     int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
     35 
     36     // Really no point in making more than 2 of these worker threads, but
     37     // we do want to limit ourselves to 1 worker thread on dual-core devices.
     38     int workerCount = cpuCount > 2 ? 2 : 1;
     39     for (int i = 0; i < workerCount; i++) {
     40         String8 name;
     41         name.appendFormat("hwuiTask%d", i + 1);
     42         mThreads.push_back(new WorkerThread(name));
     43     }
     44 }
     45 
     46 TaskManager::~TaskManager() {
     47     for (size_t i = 0; i < mThreads.size(); i++) {
     48         mThreads[i]->exit();
     49     }
     50 }
     51 
     52 bool TaskManager::canRunTasks() const {
     53     return mThreads.size() > 0;
     54 }
     55 
     56 void TaskManager::stop() {
     57     for (size_t i = 0; i < mThreads.size(); i++) {
     58         mThreads[i]->exit();
     59     }
     60 }
     61 
     62 bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
     63     if (mThreads.size() > 0) {
     64         TaskWrapper wrapper(task, processor);
     65 
     66         size_t minQueueSize = INT_MAX;
     67         sp<WorkerThread> thread;
     68 
     69         for (size_t i = 0; i < mThreads.size(); i++) {
     70             if (mThreads[i]->getTaskCount() < minQueueSize) {
     71                 thread = mThreads[i];
     72                 minQueueSize = mThreads[i]->getTaskCount();
     73             }
     74         }
     75 
     76         return thread->addTask(wrapper);
     77     }
     78     return false;
     79 }
     80 
     81 ///////////////////////////////////////////////////////////////////////////////
     82 // Thread
     83 ///////////////////////////////////////////////////////////////////////////////
     84 
     85 status_t TaskManager::WorkerThread::readyToRun() {
     86     setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
     87     return NO_ERROR;
     88 }
     89 
     90 bool TaskManager::WorkerThread::threadLoop() {
     91     mSignal.wait();
     92     std::vector<TaskWrapper> tasks;
     93     {
     94         Mutex::Autolock l(mLock);
     95         tasks.swap(mTasks);
     96     }
     97 
     98     for (size_t i = 0; i < tasks.size(); i++) {
     99         const TaskWrapper& task = tasks[i];
    100         task.mProcessor->process(task.mTask);
    101     }
    102 
    103     return true;
    104 }
    105 
    106 bool TaskManager::WorkerThread::addTask(const TaskWrapper& task) {
    107     if (!isRunning()) {
    108         run(mName.string(), PRIORITY_DEFAULT);
    109     } else if (exitPending()) {
    110         return false;
    111     }
    112 
    113     {
    114         Mutex::Autolock l(mLock);
    115         mTasks.push_back(task);
    116     }
    117     mSignal.signal();
    118 
    119     return true;
    120 }
    121 
    122 size_t TaskManager::WorkerThread::getTaskCount() const {
    123     Mutex::Autolock l(mLock);
    124     return mTasks.size();
    125 }
    126 
    127 void TaskManager::WorkerThread::exit() {
    128     requestExit();
    129     mSignal.signal();
    130 }
    131 
    132 }; // namespace uirenderer
    133 }; // namespace android
    134