1a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert/* 2a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * Copyright (C) 2009 The Android Open Source Project 3a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * 4a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 5a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * you may not use this file except in compliance with the License. 6a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * You may obtain a copy of the License at 7a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * 8a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 9a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * 10a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * Unless required by applicable law or agreed to in writing, software 11a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 12a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * See the License for the specific language governing permissions and 14a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * limitations under the License. 15a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert */ 16a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 17a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertpackage com.android.quicksearchbox.util; 18a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 19a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport android.util.Log; 20a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 21a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport java.util.concurrent.LinkedBlockingQueue; 22a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport java.util.concurrent.ThreadFactory; 23a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 24a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert/** 25a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert * Executor that uses a single thread and an unbounded work queue. 26a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert */ 27a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertpublic class SingleThreadNamedTaskExecutor implements NamedTaskExecutor { 28a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 29b5fc08b7f16a32d3865f44b7f26d8aaa5304a2adBjorn Bringert private static final boolean DBG = false; 30a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert private static final String TAG = "QSB.SingleThreadNamedTaskExecutor"; 31a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 32a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert private final LinkedBlockingQueue<NamedTask> mQueue; 33a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert private final Thread mWorker; 34a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert private volatile boolean mClosed = false; 35a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 36a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public SingleThreadNamedTaskExecutor(ThreadFactory threadFactory) { 37a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mQueue = new LinkedBlockingQueue<NamedTask>(); 38a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mWorker = threadFactory.newThread(new Worker()); 39a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mWorker.start(); 40a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 41a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 42a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public void cancelPendingTasks() { 4347d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert if (DBG) Log.d(TAG, "Cancelling " + mQueue.size() + " tasks: " + mWorker.getName()); 44a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert if (mClosed) { 45a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert throw new IllegalStateException("cancelPendingTasks() after close()"); 46a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 47a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mQueue.clear(); 48a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 49a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 50a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public void close() { 51a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mClosed = true; 52a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mWorker.interrupt(); 53a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mQueue.clear(); 54a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 55a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 56a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public void execute(NamedTask task) { 57a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert if (mClosed) { 58a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert throw new IllegalStateException("execute() after close()"); 59a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 60a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert mQueue.add(task); 61a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 62a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 63a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert private class Worker implements Runnable { 64a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public void run() { 65c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney try { 66c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney loop(); 67c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney } finally { 68c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney if (!mClosed) Log.w(TAG, "Worker exited before close"); 69c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney } 70c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney } 71c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney 72c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney private void loop() { 73c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney Thread currentThread = Thread.currentThread(); 74c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney String threadName = currentThread.getName(); 75a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert while (!mClosed) { 76a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert NamedTask task; 77a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert try { 78a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert task = mQueue.take(); 79a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } catch (InterruptedException ex) { 80c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney continue; 81a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 82c963d16e55b6dc2bf37526455ff2c05150b2bfa2Bryan Mawhinney currentThread.setName(threadName + " " + task.getName()); 83a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert try { 844572856ac85bb53ea06e65d00beebdf336af9b27Mathew Inwood if (DBG) Log.d(TAG, "Running task " + task.getName()); 85a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert task.run(); 864572856ac85bb53ea06e65d00beebdf336af9b27Mathew Inwood if (DBG) Log.d(TAG, "Task " + task.getName() + " complete"); 87a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } catch (RuntimeException ex) { 88a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert Log.e(TAG, "Task " + task.getName() + " failed", ex); 89a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 90a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 91a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 92a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 93a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 94a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public static Factory<NamedTaskExecutor> factory(final ThreadFactory threadFactory) { 95a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert return new Factory<NamedTaskExecutor>() { 96a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert public NamedTaskExecutor create() { 97a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert return new SingleThreadNamedTaskExecutor(threadFactory); 98a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 99a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert }; 100a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert } 101a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert 102a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert} 103