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#ifndef _LIBS_UTILS_WORK_QUEUE_H 180818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#define _LIBS_UTILS_WORK_QUEUE_H 190818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 200818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#include <utils/Errors.h> 210818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#include <utils/Vector.h> 220818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#include <utils/threads.h> 230818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 240818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownnamespace android { 250818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 260818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown/* 270818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * A threaded work queue. 280818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 290818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * This class is designed to make it easy to run a bunch of isolated work 300818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * units in parallel, using up to the specified number of threads. 310818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * To use it, write a loop to post work units to the work queue, then synchronize 320818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * on the queue at the end. 330818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 340818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownclass WorkQueue { 350818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownpublic: 360818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown class WorkUnit { 370818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown public: 380818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown WorkUnit() { } 390818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown virtual ~WorkUnit() { } 400818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 410818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* 420818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Runs the work unit. 430818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the result is 'true' then the work queue continues scheduling work as usual. 440818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the result is 'false' then the work queue is canceled. 450818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 460818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown virtual bool run() = 0; 470818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown }; 480818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 490818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* Creates a work queue with the specified maximum number of work threads. */ 500818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown WorkQueue(size_t maxThreads, bool canCallJava = true); 510818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 520818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* Destroys the work queue. 530818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Cancels pending work and waits for all remaining threads to complete. 540818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 550818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown ~WorkQueue(); 560818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 570818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* Posts a work unit to run later. 580818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the work queue has been canceled or is already finished, returns INVALID_OPERATION 590818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * and does not take ownership of the work unit (caller must destroy it itself). 600818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Otherwise, returns OK and takes ownership of the work unit (the work queue will 610818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * destroy it automatically). 620818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 630818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * For flow control, this method blocks when the size of the pending work queue is more 640818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 'backlog' times the number of threads. This condition reduces the rate of entry into 650818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * the pending work queue and prevents it from growing much more rapidly than the 660818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * work threads can actually handle. 670818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 680818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If 'backlog' is 0, then no throttle is applied. 690818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 700818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown status_t schedule(WorkUnit* workUnit, size_t backlog = 2); 710818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 720818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* Cancels all pending work. 730818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the work queue is already finished, returns INVALID_OPERATION. 740818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the work queue is already canceled, returns OK and does nothing else. 750818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Otherwise, returns OK, discards all pending work units and prevents additional 760818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * work units from being scheduled. 770818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * 780818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Call finish() after cancel() to wait for all remaining work to complete. 790818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 800818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown status_t cancel(); 810818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 820818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown /* Waits for all work to complete. 830818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * If the work queue is already finished, returns INVALID_OPERATION. 840818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown * Otherwise, waits for all work to complete and returns OK. 850818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown */ 860818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown status_t finish(); 870818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 880818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brownprivate: 890818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown class WorkThread : public Thread { 900818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown public: 910818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown WorkThread(WorkQueue* workQueue, bool canCallJava); 920818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown virtual ~WorkThread(); 930818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 940818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown private: 950818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown virtual bool threadLoop(); 960818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 970818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown WorkQueue* const mWorkQueue; 980818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown }; 990818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1000818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown status_t cancelLocked(); 1010818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown bool threadLoop(); // called from each work thread 1020818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1030818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown const size_t mMaxThreads; 1040818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown const bool mCanCallJava; 1050818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1060818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Mutex mLock; 1070818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Condition mWorkChangedCondition; 1080818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Condition mWorkDequeuedCondition; 1090818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1100818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown bool mCanceled; 1110818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown bool mFinished; 1120818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown size_t mIdleThreads; 1130818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Vector<sp<WorkThread> > mWorkThreads; 1140818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown Vector<WorkUnit*> mWorkUnits; 1150818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown}; 1160818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1170818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown}; // namespace android 1180818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown 1190818b0921ef6cda07f41b56d2ef19b2849dfefd1Jeff Brown#endif // _LIBS_UTILS_WORK_QUEUE_H 120