blob: 6ee4780591710d0e9eef2c29eff51906b0bef5ab [file] [log] [blame]
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07001/*
2 * Copyright (C) 2010 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 android.app;
18
19import java.util.concurrent.ConcurrentLinkedQueue;
20import java.util.concurrent.ExecutorService;
21import java.util.concurrent.Executors;
22
23/**
24 * Internal utility class to keep track of process-global work that's
25 * outstanding and hasn't been finished yet.
26 *
27 * This was created for writing SharedPreference edits out
28 * asynchronously so we'd have a mechanism to wait for the writes in
29 * Activity.onPause and similar places, but we may use this mechanism
30 * for other things in the future.
31 *
32 * @hide
33 */
34public class QueuedWork {
35
36 // The set of Runnables that will finish or wait on any async
37 // activities started by the application.
38 private static final ConcurrentLinkedQueue<Runnable> sPendingWorkFinishers =
39 new ConcurrentLinkedQueue<Runnable>();
40
41 private static ExecutorService sSingleThreadExecutor = null; // lazy, guarded by class
42
43 /**
44 * Returns a single-thread Executor shared by the entire process,
45 * creating it if necessary.
46 */
47 public static ExecutorService singleThreadExecutor() {
48 synchronized (QueuedWork.class) {
49 if (sSingleThreadExecutor == null) {
50 // TODO: can we give this single thread a thread name?
51 sSingleThreadExecutor = Executors.newSingleThreadExecutor();
52 }
53 return sSingleThreadExecutor;
54 }
55 }
56
57 /**
58 * Add a runnable to finish (or wait for) a deferred operation
59 * started in this context earlier. Typically finished by e.g.
60 * an Activity#onPause. Used by SharedPreferences$Editor#startCommit().
61 *
62 * Note that this doesn't actually start it running. This is just
63 * a scratch set for callers doing async work to keep updated with
64 * what's in-flight. In the common case, caller code
65 * (e.g. SharedPreferences) will pretty quickly call remove()
66 * after an add(). The only time these Runnables are run is from
67 * waitToFinish(), below.
68 */
69 public static void add(Runnable finisher) {
70 sPendingWorkFinishers.add(finisher);
71 }
72
73 public static void remove(Runnable finisher) {
74 sPendingWorkFinishers.remove(finisher);
75 }
76
77 /**
78 * Finishes or waits for async operations to complete.
79 * (e.g. SharedPreferences$Editor#startCommit writes)
80 *
81 * Is called from the Activity base class's onPause(), after
82 * BroadcastReceiver's onReceive, after Service command handling,
83 * etc. (so async work is never lost)
84 */
85 public static void waitToFinish() {
86 Runnable toFinish;
87 while ((toFinish = sPendingWorkFinishers.poll()) != null) {
88 toFinish.run();
89 }
90 }
Dianne Hackborne829fef2010-10-26 17:44:01 -070091
92 /**
93 * Returns true if there is pending work to be done. Note that the
94 * result is out of data as soon as you receive it, so be careful how you
95 * use it.
96 */
97 public static boolean hasPendingWork() {
98 return !sPendingWorkFinishers.isEmpty();
99 }
100
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700101}