WorkQueue.cpp revision 0818b0921ef6cda07f41b56d2ef19b2849dfefd1
10818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown/* 20818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Copyright (C) 2012 The Android Open Source Project 30818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 40818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 50818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * you may not use this file except in compliance with the License. 60818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * You may obtain a copy of the License at 70818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 80818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 90818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 100818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Unless required by applicable law or agreed to in writing, software 110818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 120818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * See the License for the specific language governing permissions and 140818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * limitations under the License. 150818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 160818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 170818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown// #define LOG_NDEBUG 0 180818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#define LOG_TAG "WorkQueue" 190818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 200818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#include <utils/Log.h> 210818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#include <utils/WorkQueue.h> 220818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 230818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownnamespace android { 240818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 250818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown// --- WorkQueue --- 260818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 270818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff BrownWorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) : 280818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mMaxThreads(maxThreads), mCanCallJava(canCallJava), 290818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mCanceled(false), mFinished(false), mIdleThreads(0) { 300818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 310818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 320818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff BrownWorkQueue::~WorkQueue() { 330818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (!cancel()) { 340818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown finish(); 350818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 360818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 370818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 380818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownstatus_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) { 390818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown AutoMutex _l(mLock); 400818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 410818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mFinished || mCanceled) { 420818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return INVALID_OPERATION; 430818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 440818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 450818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mWorkThreads.size() < mMaxThreads 460818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown && mIdleThreads < mWorkUnits.size() + 1) { 470818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown sp<WorkThread> workThread = new WorkThread(this, mCanCallJava); 480818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown status_t status = workThread->run("WorkQueue::WorkThread"); 490818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (status) { 500818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return status; 510818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 520818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkThreads.add(workThread); 530818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mIdleThreads += 1; 540818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } else if (backlog) { 550818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown while (mWorkUnits.size() >= mMaxThreads * backlog) { 560818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkDequeuedCondition.wait(mLock); 570818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mFinished || mCanceled) { 580818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return INVALID_OPERATION; 590818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 600818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 610818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 620818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 630818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkUnits.add(workUnit); 640818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkChangedCondition.broadcast(); 650818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return OK; 660818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 670818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 680818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownstatus_t WorkQueue::cancel() { 690818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown AutoMutex _l(mLock); 700818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 710818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return cancelLocked(); 720818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 730818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 740818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownstatus_t WorkQueue::cancelLocked() { 750818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mFinished) { 760818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return INVALID_OPERATION; 770818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 780818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 790818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (!mCanceled) { 800818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mCanceled = true; 810818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 820818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown size_t count = mWorkUnits.size(); 830818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown for (size_t i = 0; i < count; i++) { 840818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown delete mWorkUnits.itemAt(i); 850818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 860818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkUnits.clear(); 870818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkChangedCondition.broadcast(); 880818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkDequeuedCondition.broadcast(); 890818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 900818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return OK; 910818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 920818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 930818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownstatus_t WorkQueue::finish() { 940818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown { // acquire lock 950818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown AutoMutex _l(mLock); 960818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 970818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mFinished) { 980818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return INVALID_OPERATION; 990818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1000818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1010818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mFinished = true; 1020818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkChangedCondition.broadcast(); 1030818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } // release lock 1040818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1050818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown // It is not possible for the list of work threads to change once the mFinished 1060818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown // flag has been set, so we can access mWorkThreads outside of the lock here. 1070818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown size_t count = mWorkThreads.size(); 1080818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown for (size_t i = 0; i < count; i++) { 1090818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkThreads.itemAt(i)->join(); 1100818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1110818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkThreads.clear(); 1120818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return OK; 1130818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 1140818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1150818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownbool WorkQueue::threadLoop() { 1160818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown WorkUnit* workUnit; 1170818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown { // acquire lock 1180818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown AutoMutex _l(mLock); 1190818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1200818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown for (;;) { 1210818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mCanceled) { 1220818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return false; 1230818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1240818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1250818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (!mWorkUnits.isEmpty()) { 1260818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown workUnit = mWorkUnits.itemAt(0); 1270818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkUnits.removeAt(0); 1280818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mIdleThreads -= 1; 1290818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkDequeuedCondition.broadcast(); 1300818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown break; 1310818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1320818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1330818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (mFinished) { 1340818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return false; 1350818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1360818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1370818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mWorkChangedCondition.wait(mLock); 1380818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1390818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } // release lock 1400818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1410818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown bool shouldContinue = workUnit->run(); 1420818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown delete workUnit; 1430818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1440818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown { // acquire lock 1450818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown AutoMutex _l(mLock); 1460818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1470818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown mIdleThreads += 1; 1480818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1490818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown if (!shouldContinue) { 1500818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown cancelLocked(); 1510818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return false; 1520818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } 1530818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown } // release lock 1540818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1550818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return true; 1560818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 1570818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1580818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown// --- WorkQueue::WorkThread --- 1590818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1600818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff BrownWorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) : 1610818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Thread(canCallJava), mWorkQueue(workQueue) { 1620818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 1630818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1640818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff BrownWorkQueue::WorkThread::~WorkThread() { 1650818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 1660818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1670818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownbool WorkQueue::WorkThread::threadLoop() { 1680818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown return mWorkQueue->threadLoop(); 1690818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown} 1700818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1710818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown}; // namespace android 172