• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TaskManager()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 
~TaskManager()41 TaskManager::~TaskManager() {
42     for (size_t i = 0; i < mThreads.size(); i++) {
43         mThreads[i]->exit();
44     }
45 }
46 
canRunTasks() const47 bool TaskManager::canRunTasks() const {
48     return mThreads.size() > 0;
49 }
50 
stop()51 void TaskManager::stop() {
52     for (size_t i = 0; i < mThreads.size(); i++) {
53         mThreads[i]->exit();
54     }
55 }
56 
addTaskBase(const sp<TaskBase> & task,const sp<TaskProcessorBase> & processor)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 
threadLoop()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 
addTask(TaskWrapper task)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 
getTaskCount() const109 size_t TaskManager::WorkerThread::getTaskCount() const {
110     Mutex::Autolock l(mLock);
111     return mTasks.size();
112 }
113 
exit()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