1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2012 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// #define LOG_NDEBUG 0 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#define LOG_TAG "WorkQueue" 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Log.h> 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "WorkQueue.h" 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskinamespace android { 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// --- WorkQueue --- 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiWorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) : 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mMaxThreads(maxThreads), mCanCallJava(canCallJava), 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mCanceled(false), mFinished(false), mIdleThreads(0) { 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiWorkQueue::~WorkQueue() { 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!cancel()) { 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski finish(); 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) { 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AutoMutex _l(mLock); 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFinished || mCanceled) { 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return INVALID_OPERATION; 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mWorkThreads.size() < mMaxThreads 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && mIdleThreads < mWorkUnits.size() + 1) { 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<WorkThread> workThread = new WorkThread(this, mCanCallJava); 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t status = workThread->run("WorkQueue::WorkThread"); 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (status) { 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return status; 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkThreads.add(workThread); 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mIdleThreads += 1; 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (backlog) { 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (mWorkUnits.size() >= mMaxThreads * backlog) { 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkDequeuedCondition.wait(mLock); 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFinished || mCanceled) { 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return INVALID_OPERATION; 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkUnits.add(workUnit); 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkChangedCondition.broadcast(); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return OK; 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t WorkQueue::cancel() { 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AutoMutex _l(mLock); 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return cancelLocked(); 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t WorkQueue::cancelLocked() { 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFinished) { 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return INVALID_OPERATION; 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!mCanceled) { 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mCanceled = true; 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t count = mWorkUnits.size(); 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i = 0; i < count; i++) { 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete mWorkUnits.itemAt(i); 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkUnits.clear(); 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkChangedCondition.broadcast(); 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkDequeuedCondition.broadcast(); 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return OK; 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t WorkQueue::finish() { 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { // acquire lock 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AutoMutex _l(mLock); 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFinished) { 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return INVALID_OPERATION; 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mFinished = true; 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkChangedCondition.broadcast(); 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } // release lock 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // It is not possible for the list of work threads to change once the mFinished 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // flag has been set, so we can access mWorkThreads outside of the lock here. 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t count = mWorkThreads.size(); 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i = 0; i < count; i++) { 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkThreads.itemAt(i)->join(); 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkThreads.clear(); 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return OK; 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool WorkQueue::threadLoop() { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski WorkUnit* workUnit; 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { // acquire lock 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AutoMutex _l(mLock); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (;;) { 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mCanceled) { 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!mWorkUnits.isEmpty()) { 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski workUnit = mWorkUnits.itemAt(0); 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkUnits.removeAt(0); 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mIdleThreads -= 1; 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkDequeuedCondition.broadcast(); 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFinished) { 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mWorkChangedCondition.wait(mLock); 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } // release lock 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool shouldContinue = workUnit->run(); 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete workUnit; 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { // acquire lock 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AutoMutex _l(mLock); 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mIdleThreads += 1; 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!shouldContinue) { 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cancelLocked(); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } // release lock 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// --- WorkQueue::WorkThread --- 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiWorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) : 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Thread(canCallJava), mWorkQueue(workQueue) { 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiWorkQueue::WorkThread::~WorkThread() { 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool WorkQueue::WorkThread::threadLoop() { 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mWorkQueue->threadLoop(); 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; // namespace android 172