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     int workerCount = MathUtils::max(1, cpuCount / 2);
     37     for (int i = 0; i < workerCount; i++) {
     38         String8 name;
     39         name.appendFormat("hwuiTask%d", i + 1);
     40         mThreads.add(new WorkerThread(name));
     41     }
     42 }
     43 
     44 TaskManager::~TaskManager() {
     45     for (size_t i = 0; i < mThreads.size(); i++) {
     46         mThreads[i]->exit();
     47     }
     48 }
     49 
     50 bool TaskManager::canRunTasks() const {
     51     return mThreads.size() > 0;
     52 }
     53 
     54 void TaskManager::stop() {
     55     for (size_t i = 0; i < mThreads.size(); i++) {
     56         mThreads[i]->exit();
     57     }
     58 }
     59 
     60 bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
     61     if (mThreads.size() > 0) {
     62         TaskWrapper wrapper(task, processor);
     63 
     64         size_t minQueueSize = INT_MAX;
     65         sp<WorkerThread> thread;
     66 
     67         for (size_t i = 0; i < mThreads.size(); i++) {
     68             if (mThreads[i]->getTaskCount() < minQueueSize) {
     69                 thread = mThreads[i];
     70                 minQueueSize = mThreads[i]->getTaskCount();
     71             }
     72         }
     73 
     74         return thread->addTask(wrapper);
     75     }
     76     return false;
     77 }
     78 
     79 ///////////////////////////////////////////////////////////////////////////////
     80 // Thread
     81 ///////////////////////////////////////////////////////////////////////////////
     82 
     83 status_t TaskManager::WorkerThread::readyToRun() {
     84     setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
     85     return NO_ERROR;
     86 }
     87 
     88 bool TaskManager::WorkerThread::threadLoop() {
     89     mSignal.wait();
     90     Vector<TaskWrapper> tasks;
     91     {
     92         Mutex::Autolock l(mLock);
     93         tasks = mTasks;
     94         mTasks.clear();
     95     }
     96 
     97     for (size_t i = 0; i < tasks.size(); i++) {
     98         const TaskWrapper& task = tasks.itemAt(i);
     99         task.mProcessor->process(task.mTask);
    100     }
    101 
    102     return true;
    103 }
    104 
    105 bool TaskManager::WorkerThread::addTask(TaskWrapper task) {
    106     if (!isRunning()) {
    107         run(mName.string(), PRIORITY_DEFAULT);
    108     } else if (exitPending()) {
    109         return false;
    110     }
    111 
    112     ssize_t index;
    113     {
    114         Mutex::Autolock l(mLock);
    115         index = mTasks.add(task);
    116     }
    117     mSignal.signal();
    118 
    119     return index >= 0;
    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