1d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey/* 2d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * 4d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * you may not use this file except in compliance with the License. 6d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * You may obtain a copy of the License at 7d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * 8d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * 10d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * See the License for the specific language governing permissions and 14d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey * limitations under the License. 15d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey */ 16d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 17d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeypackage com.android.documentsui; 18d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 19b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkeyimport android.os.AsyncTask; 20b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 21d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport com.android.internal.annotations.GuardedBy; 22d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport com.android.internal.util.Preconditions; 23b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkeyimport com.google.android.collect.Lists; 24d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport com.google.android.collect.Maps; 25d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 26b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkeyimport java.lang.ref.WeakReference; 27b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkeyimport java.util.ArrayList; 28d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport java.util.HashMap; 29d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport java.util.concurrent.Executor; 30d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeyimport java.util.concurrent.LinkedBlockingQueue; 31d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 32d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkeypublic class ProviderExecutor extends Thread implements Executor { 33d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 34d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey @GuardedBy("sExecutors") 35d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap(); 36d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 37b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey public static ProviderExecutor forAuthority(String authority) { 38d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey synchronized (sExecutors) { 39d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey ProviderExecutor executor = sExecutors.get(authority); 40d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey if (executor == null) { 41d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey executor = new ProviderExecutor(); 42d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey executor.setName("ProviderExecutor: " + authority); 43d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey executor.start(); 44d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey sExecutors.put(authority, executor); 45d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 46d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey return executor; 47d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 48d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 49d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 50b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey public interface Preemptable { 51b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey void preempt(); 52b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 53b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 54d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>(); 55d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 56b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList(); 57b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 58b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey private void preempt() { 59b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey synchronized (mPreemptable) { 60b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey int count = 0; 61b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey for (WeakReference<Preemptable> ref : mPreemptable) { 62b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey final Preemptable p = ref.get(); 63b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey if (p != null) { 64b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey count++; 65b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey p.preempt(); 66b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 67b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 68b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey mPreemptable.clear(); 69b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 70b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 71b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 72b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey /** 73b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey * Execute the given task. If given task is not {@link Preemptable}, it will 74b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey * preempt all outstanding preemptable tasks. 75b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey */ 76b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey public <P> void execute(AsyncTask<P, ?, ?> task, P... params) { 77b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey if (task instanceof Preemptable) { 78b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey synchronized (mPreemptable) { 79b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task)); 80b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 81b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey task.executeOnExecutor(mNonPreemptingExecutor, params); 82b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } else { 83b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey task.executeOnExecutor(this, params); 84b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 85b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 86b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 87b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey private Executor mNonPreemptingExecutor = new Executor() { 88b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey @Override 89b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey public void execute(Runnable command) { 90b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey Preconditions.checkNotNull(command); 91b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey mQueue.add(command); 92b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey } 93b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey }; 94b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey 95d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey @Override 96d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey public void execute(Runnable command) { 97b3d42635aafacd80b1e1d257338ea6abb93d22c3Jeff Sharkey preempt(); 98d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey Preconditions.checkNotNull(command); 99d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey mQueue.add(command); 100d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 101d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey 102d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey @Override 103d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey public void run() { 104d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey while (true) { 105d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey try { 106d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey final Runnable command = mQueue.take(); 107d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey command.run(); 108d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } catch (InterruptedException e) { 109d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey // That was weird; let's go look for more tasks. 110d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 111d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 112d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey } 113d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey} 114