blob: b0e332faa3fcae9037e1847b2023b917dce09492 [file] [log] [blame]
Jeff Sharkeyd01571e2013-10-01 17:57:41 -07001/*
2 * Copyright (C) 2013 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.documentsui;
18
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070019import android.os.AsyncTask;
20
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070021import com.android.internal.annotations.GuardedBy;
22import com.android.internal.util.Preconditions;
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070023
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070024import java.lang.ref.WeakReference;
25import java.util.ArrayList;
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070026import java.util.HashMap;
27import java.util.concurrent.Executor;
28import java.util.concurrent.LinkedBlockingQueue;
29
30public class ProviderExecutor extends Thread implements Executor {
31
32 @GuardedBy("sExecutors")
Steve McKay58efce32015-08-20 16:19:38 +000033 private static HashMap<String, ProviderExecutor> sExecutors = new HashMap<>();
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070034
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070035 public static ProviderExecutor forAuthority(String authority) {
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070036 synchronized (sExecutors) {
37 ProviderExecutor executor = sExecutors.get(authority);
38 if (executor == null) {
39 executor = new ProviderExecutor();
40 executor.setName("ProviderExecutor: " + authority);
41 executor.start();
42 sExecutors.put(authority, executor);
43 }
44 return executor;
45 }
46 }
47
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070048 public interface Preemptable {
49 void preempt();
50 }
51
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070052 private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
53
Steve McKay58efce32015-08-20 16:19:38 +000054 private final ArrayList<WeakReference<Preemptable>> mPreemptable = new ArrayList<>();
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070055
56 private void preempt() {
57 synchronized (mPreemptable) {
58 int count = 0;
59 for (WeakReference<Preemptable> ref : mPreemptable) {
60 final Preemptable p = ref.get();
61 if (p != null) {
62 count++;
63 p.preempt();
64 }
65 }
66 mPreemptable.clear();
67 }
68 }
69
70 /**
71 * Execute the given task. If given task is not {@link Preemptable}, it will
72 * preempt all outstanding preemptable tasks.
73 */
74 public <P> void execute(AsyncTask<P, ?, ?> task, P... params) {
75 if (task instanceof Preemptable) {
76 synchronized (mPreemptable) {
77 mPreemptable.add(new WeakReference<Preemptable>((Preemptable) task));
78 }
79 task.executeOnExecutor(mNonPreemptingExecutor, params);
80 } else {
81 task.executeOnExecutor(this, params);
82 }
83 }
84
85 private Executor mNonPreemptingExecutor = new Executor() {
86 @Override
87 public void execute(Runnable command) {
88 Preconditions.checkNotNull(command);
89 mQueue.add(command);
90 }
91 };
92
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070093 @Override
94 public void execute(Runnable command) {
Jeff Sharkeyb3d42632013-10-22 17:09:44 -070095 preempt();
Jeff Sharkeyd01571e2013-10-01 17:57:41 -070096 Preconditions.checkNotNull(command);
97 mQueue.add(command);
98 }
99
100 @Override
101 public void run() {
102 while (true) {
103 try {
104 final Runnable command = mQueue.take();
105 command.run();
106 } catch (InterruptedException e) {
107 // That was weird; let's go look for more tasks.
108 }
109 }
110 }
111}