OSDN Git Service

Treat document thumbnails as preemptable.
[android-x86/frameworks-base.git] / packages / DocumentsUI / src / com / android / documentsui / ProviderExecutor.java
index 2105cb4..f94aebd 100644 (file)
 
 package com.android.documentsui;
 
+import android.os.AsyncTask;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -29,7 +34,7 @@ public class ProviderExecutor extends Thread implements Executor {
     @GuardedBy("sExecutors")
     private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap();
 
-    public static Executor forAuthority(String authority) {
+    public static ProviderExecutor forAuthority(String authority) {
         synchronized (sExecutors) {
             ProviderExecutor executor = sExecutors.get(authority);
             if (executor == null) {
@@ -42,10 +47,54 @@ public class ProviderExecutor extends Thread implements Executor {
         }
     }
 
+    public interface Preemptable {
+        void preempt();
+    }
+
     private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
 
+    private final ArrayList<WeakReference<Preemptable>> mPreemptable = Lists.newArrayList();
+
+    private void preempt() {
+        synchronized (mPreemptable) {
+            int count = 0;
+            for (WeakReference<Preemptable> ref : mPreemptable) {
+                final Preemptable p = ref.get();
+                if (p != null) {
+                    count++;
+                    p.preempt();
+                }
+            }
+            mPreemptable.clear();
+        }
+    }
+
+    /**
+     * Execute the given task. If given task is not {@link Preemptable}, it will
+     * preempt all outstanding preemptable tasks.
+     */
+    public <P> void execute(AsyncTask<P, ?, ?> task, P... params) {
+        if (task instanceof Preemptable) {
+            synchronized (mPreemptable) {
+                mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task));
+            }
+            task.executeOnExecutor(mNonPreemptingExecutor, params);
+        } else {
+            task.executeOnExecutor(this, params);
+        }
+    }
+
+    private Executor mNonPreemptingExecutor = new Executor() {
+        @Override
+        public void execute(Runnable command) {
+            Preconditions.checkNotNull(command);
+            mQueue.add(command);
+        }
+    };
+
     @Override
     public void execute(Runnable command) {
+        preempt();
         Preconditions.checkNotNull(command);
         mQueue.add(command);
     }