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/sysinfo.h>
     18 
     19 #include "Task.h"
     20 #include "TaskProcessor.h"
     21 #include "TaskManager.h"
     22 
     23 namespace android {
     24 namespace uirenderer {
     25 
     26 ///////////////////////////////////////////////////////////////////////////////
     27 // Manager
     28 ///////////////////////////////////////////////////////////////////////////////
     29 
     30 TaskManager::TaskManager() {
     31     // Get the number of available CPUs. This value does not change over time.
     32     int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
     33 
     34     for (int i = 0; i < cpuCount / 2; i++) {
     35         String8 name;
     36         name.appendFormat("hwuiTask%d", i + 1);
     37         mThreads.add(new WorkerThread(name));
     38     }
     39 }
     40 
     41 TaskManager::~TaskManager() {
     42     for (size_t i = 0; i < mThreads.size(); i++) {
     43         mThreads[i]->exit();
     44     }
     45 }
     46 
     47 bool TaskManager::canRunTasks() const {
     48     return mThreads.size() > 0;
     49 }
     50 
     51 void TaskManager::stop() {
     52     for (size_t i = 0; i < mThreads.size(); i++) {
     53         mThreads[i]->exit();
     54     }
     55 }
     56 
     57 bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
     58     if (mThreads.size() > 0) {
     59         TaskWrapper wrapper(task, processor);
     60 
     61         size_t minQueueSize = INT_MAX;
     62         sp<WorkerThread> thread;
     63 
     64         for (size_t i = 0; i < mThreads.size(); i++) {
     65             if (mThreads[i]->getTaskCount() < minQueueSize) {
     66                 thread = mThreads[i];
     67                 minQueueSize = mThreads[i]->getTaskCount();
     68             }
     69         }
     70 
     71         return thread->addTask(wrapper);
     72     }
     73     return false;
     74 }
     75 
     76 ///////////////////////////////////////////////////////////////////////////////
     77 // Thread
     78 ///////////////////////////////////////////////////////////////////////////////
     79 
     80 bool TaskManager::WorkerThread::threadLoop() {
     81     mSignal.wait();
     82     Vector<TaskWrapper> tasks;
     83     {
     84         Mutex::Autolock l(mLock);
     85         tasks = mTasks;
     86         mTasks.clear();
     87     }
     88 
     89     for (size_t i = 0; i < tasks.size(); i++) {
     90         const TaskWrapper& task = tasks.itemAt(i);
     91         task.mProcessor->process(task.mTask);
     92     }
     93 
     94     return true;
     95 }
     96 
     97 bool TaskManager::WorkerThread::addTask(TaskWrapper task) {
     98     if (!isRunning()) {
     99         run(mName.string(), PRIORITY_DEFAULT);
    100     }
    101 
    102     Mutex::Autolock l(mLock);
    103     ssize_t index = mTasks.add(task);
    104     mSignal.signal();
    105 
    106     return index >= 0;
    107 }
    108 
    109 size_t TaskManager::WorkerThread::getTaskCount() const {
    110     Mutex::Autolock l(mLock);
    111     return mTasks.size();
    112 }
    113 
    114 void TaskManager::WorkerThread::exit() {
    115     {
    116         Mutex::Autolock l(mLock);
    117         mTasks.clear();
    118     }
    119     requestExit();
    120     mSignal.signal();
    121 }
    122 
    123 }; // namespace uirenderer
    124 }; // namespace android
    125