BatchingNamedTaskExecutor.java revision a48af083ff81555261f334a1e050eae3b02a746c
1/* 2 * Copyright (C) 2010 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 17package com.android.quicksearchbox.util; 18 19 20import android.util.Log; 21 22import java.util.ArrayList; 23import java.util.List; 24 25/** 26 * Executes NamedTasks in batches of a predefined size. Tasks in excess of 27 * the batch size are queued until the caller indicates that more results 28 * are required. 29 */ 30public class BatchingNamedTaskExecutor implements NamedTaskExecutor { 31 32 private static final boolean DBG = true; 33 private static final String TAG = "QSB.BatchingNamedTaskExecutor"; 34 35 private final NamedTaskExecutor mExecutor; 36 37 private final int mBatchSize; 38 39 /** Queue of tasks waiting to be dispatched to mExecutor **/ 40 private final ArrayList<NamedTask> mQueuedTasks = new ArrayList<NamedTask>(); 41 42 /** Count of tasks already dispatched to mExecutor in this batch **/ 43 private int mDispatchedCount; 44 45 /** 46 * Creates a new BatchingSourceTaskExecutor. 47 * 48 * @param executor A SourceTaskExecutor for actually executing the tasks. 49 * @param batchSize The number of tasks to submit in each batch. 50 */ 51 public BatchingNamedTaskExecutor(NamedTaskExecutor executor, int batchSize) { 52 mExecutor = executor; 53 mBatchSize = batchSize; 54 } 55 56 public void execute(NamedTask task) { 57 synchronized (mQueuedTasks) { 58 if (mDispatchedCount == mBatchSize) { 59 if (DBG) Log.d(TAG, "Queueing " + task); 60 mQueuedTasks.add(task); 61 return; 62 } 63 mDispatchedCount++; 64 } 65 // Avoid holding the lock when dispatching the task. 66 dispatch(task); 67 } 68 69 private void dispatch(NamedTask task) { 70 if (DBG) Log.d(TAG, "Dispatching " + task); 71 mExecutor.execute(task); 72 } 73 74 /** 75 * Instructs the executor to submit the next batch of results. 76 */ 77 public void executeNextBatch() { 78 NamedTask[] batch = new NamedTask[0]; 79 synchronized (mQueuedTasks) { 80 int count = Math.min(mQueuedTasks.size(), mBatchSize); 81 List<NamedTask> nextTasks = mQueuedTasks.subList(0, count); 82 batch = nextTasks.toArray(batch); 83 nextTasks.clear(); 84 mDispatchedCount = count; 85 if (DBG) Log.d(TAG, "Dispatching batch of " + count); 86 } 87 88 for (NamedTask task : batch) { 89 dispatch(task); 90 } 91 } 92 93 /** 94 * Cancel any unstarted tasks running in this executor. This instance 95 * should not be re-used after calling this method. 96 */ 97 public void cancelPendingTasks() { 98 synchronized (mQueuedTasks) { 99 mQueuedTasks.clear(); 100 mDispatchedCount = 0; 101 } 102 mExecutor.cancelPendingTasks(); 103 } 104 105 public void close() { 106 cancelPendingTasks(); 107 mExecutor.close(); 108 } 109} 110