/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.documentsui; import android.os.AsyncTask; import androidx.annotation.GuardedBy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; public class ProviderExecutor extends Thread implements Executor { @GuardedBy("sExecutors") private static HashMap sExecutors = new HashMap<>(); public static ProviderExecutor forAuthority(String authority) { synchronized (sExecutors) { ProviderExecutor executor = sExecutors.get(authority); if (executor == null) { executor = new ProviderExecutor(); executor.setName("ProviderExecutor: " + authority); executor.start(); sExecutors.put(authority, executor); } return executor; } } public interface Preemptable { void preempt(); } private final LinkedBlockingQueue mQueue = new LinkedBlockingQueue(); private final ArrayList> mPreemptable = new ArrayList<>(); private void preempt() { synchronized (mPreemptable) { int count = 0; for (WeakReference 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

void execute(AsyncTask task, P... params) { if (task instanceof Preemptable) { synchronized (mPreemptable) { mPreemptable.add(new WeakReference((Preemptable) task)); } task.executeOnExecutor(mNonPreemptingExecutor, params); } else { task.executeOnExecutor(this, params); } } private Executor mNonPreemptingExecutor = new Executor() { @Override public void execute(Runnable command) { assert(command != null); mQueue.add(command); } }; @Override public void execute(Runnable command) { preempt(); assert(command != null); mQueue.add(command); } @Override public void run() { while (true) { try { final Runnable command = mQueue.take(); command.run(); } catch (InterruptedException e) { // That was weird; let's go look for more tasks. } } } }