1 /*] 2 * Copyright (C) 2012 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 #ifndef AAPT_WORK_QUEUE_H 18 #define AAPT_WORK_QUEUE_H 19 20 #include <utils/Errors.h> 21 #include <utils/Vector.h> 22 #include <utils/threads.h> 23 24 namespace android { 25 26 /* 27 * A threaded work queue. 28 * 29 * This class is designed to make it easy to run a bunch of isolated work 30 * units in parallel, using up to the specified number of threads. 31 * To use it, write a loop to post work units to the work queue, then synchronize 32 * on the queue at the end. 33 */ 34 class WorkQueue { 35 public: 36 class WorkUnit { 37 public: WorkUnit()38 WorkUnit() { } ~WorkUnit()39 virtual ~WorkUnit() { } 40 41 /* 42 * Runs the work unit. 43 * If the result is 'true' then the work queue continues scheduling work as usual. 44 * If the result is 'false' then the work queue is canceled. 45 */ 46 virtual bool run() = 0; 47 }; 48 49 /* Creates a work queue with the specified maximum number of work threads. */ 50 WorkQueue(size_t maxThreads, bool canCallJava = true); 51 52 /* Destroys the work queue. 53 * Cancels pending work and waits for all remaining threads to complete. 54 */ 55 ~WorkQueue(); 56 57 /* Posts a work unit to run later. 58 * If the work queue has been canceled or is already finished, returns INVALID_OPERATION 59 * and does not take ownership of the work unit (caller must destroy it itself). 60 * Otherwise, returns OK and takes ownership of the work unit (the work queue will 61 * destroy it automatically). 62 * 63 * For flow control, this method blocks when the size of the pending work queue is more 64 * 'backlog' times the number of threads. This condition reduces the rate of entry into 65 * the pending work queue and prevents it from growing much more rapidly than the 66 * work threads can actually handle. 67 * 68 * If 'backlog' is 0, then no throttle is applied. 69 */ 70 status_t schedule(WorkUnit* workUnit, size_t backlog = 2); 71 72 /* Cancels all pending work. 73 * If the work queue is already finished, returns INVALID_OPERATION. 74 * If the work queue is already canceled, returns OK and does nothing else. 75 * Otherwise, returns OK, discards all pending work units and prevents additional 76 * work units from being scheduled. 77 * 78 * Call finish() after cancel() to wait for all remaining work to complete. 79 */ 80 status_t cancel(); 81 82 /* Waits for all work to complete. 83 * If the work queue is already finished, returns INVALID_OPERATION. 84 * Otherwise, waits for all work to complete and returns OK. 85 */ 86 status_t finish(); 87 88 private: 89 class WorkThread : public Thread { 90 public: 91 WorkThread(WorkQueue* workQueue, bool canCallJava); 92 virtual ~WorkThread(); 93 94 private: 95 virtual bool threadLoop(); 96 97 WorkQueue* const mWorkQueue; 98 }; 99 100 status_t cancelLocked(); 101 bool threadLoop(); // called from each work thread 102 103 const size_t mMaxThreads; 104 const bool mCanCallJava; 105 106 Mutex mLock; 107 Condition mWorkChangedCondition; 108 Condition mWorkDequeuedCondition; 109 110 bool mCanceled; 111 bool mFinished; 112 size_t mIdleThreads; 113 Vector<sp<WorkThread> > mWorkThreads; 114 Vector<WorkUnit*> mWorkUnits; 115 }; 116 117 }; // namespace android 118 119 #endif // AAPT_WORK_QUEUE_H 120