1333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick/*
2333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * Copyright (C) 2010 The Android Open Source Project
3333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *
4333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * Licensed under the Apache License, Version 2.0 (the "License");
5333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * you may not use this file except in compliance with the License.
6333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * You may obtain a copy of the License at
7333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *
8333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *      http://www.apache.org/licenses/LICENSE-2.0
9333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *
10333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * Unless required by applicable law or agreed to in writing, software
11333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * distributed under the License is distributed on an "AS IS" BASIS,
12333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * See the License for the specific language governing permissions and
14333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * limitations under the License.
15333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick */
16333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
17333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrickpackage android.app;
18333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
19333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrickimport java.util.concurrent.ConcurrentLinkedQueue;
20333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrickimport java.util.concurrent.ExecutorService;
21333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrickimport java.util.concurrent.Executors;
22333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
23333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick/**
24333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * Internal utility class to keep track of process-global work that's
25333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * outstanding and hasn't been finished yet.
26333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *
27333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * This was created for writing SharedPreference edits out
28333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * asynchronously so we'd have a mechanism to wait for the writes in
29333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * Activity.onPause and similar places, but we may use this mechanism
30333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * for other things in the future.
31333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick *
32333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick * @hide
33333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick */
34333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrickpublic class QueuedWork {
35333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
36333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    // The set of Runnables that will finish or wait on any async
37333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    // activities started by the application.
38333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    private static final ConcurrentLinkedQueue<Runnable> sPendingWorkFinishers =
39333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick            new ConcurrentLinkedQueue<Runnable>();
40333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
41333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    private static ExecutorService sSingleThreadExecutor = null; // lazy, guarded by class
42333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
43333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    /**
44333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * Returns a single-thread Executor shared by the entire process,
45333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * creating it if necessary.
46333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     */
47333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    public static ExecutorService singleThreadExecutor() {
48333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        synchronized (QueuedWork.class) {
49333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick            if (sSingleThreadExecutor == null) {
50333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick                // TODO: can we give this single thread a thread name?
51333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick                sSingleThreadExecutor = Executors.newSingleThreadExecutor();
52333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick            }
53333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick            return sSingleThreadExecutor;
54333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        }
55333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    }
56333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
57333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    /**
58333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * Add a runnable to finish (or wait for) a deferred operation
59333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * started in this context earlier.  Typically finished by e.g.
60333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * an Activity#onPause.  Used by SharedPreferences$Editor#startCommit().
61333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     *
62333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * Note that this doesn't actually start it running.  This is just
63333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * a scratch set for callers doing async work to keep updated with
64333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * what's in-flight.  In the common case, caller code
65333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * (e.g. SharedPreferences) will pretty quickly call remove()
66333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * after an add().  The only time these Runnables are run is from
67333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * waitToFinish(), below.
68333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     */
69333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    public static void add(Runnable finisher) {
70333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        sPendingWorkFinishers.add(finisher);
71333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    }
72333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
73333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    public static void remove(Runnable finisher) {
74333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        sPendingWorkFinishers.remove(finisher);
75333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    }
76333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick
77333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    /**
78333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * Finishes or waits for async operations to complete.
79333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * (e.g. SharedPreferences$Editor#startCommit writes)
80333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     *
81333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * Is called from the Activity base class's onPause(), after
82333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * BroadcastReceiver's onReceive, after Service command handling,
83333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     * etc.  (so async work is never lost)
84333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick     */
85333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    public static void waitToFinish() {
86333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        Runnable toFinish;
87333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        while ((toFinish = sPendingWorkFinishers.poll()) != null) {
88333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick            toFinish.run();
89333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick        }
90333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick    }
91e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn
92e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn    /**
93e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn     * Returns true if there is pending work to be done.  Note that the
94e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn     * result is out of data as soon as you receive it, so be careful how you
95e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn     * use it.
96e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn     */
97e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn    public static boolean hasPendingWork() {
98e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn        return !sPendingWorkFinishers.isEmpty();
99e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn    }
100e829fef63957a23b61cdb01bb692a17a041ff2dcDianne Hackborn
101333b8cba996c8ebb8ca55ebfc5cc536bdd64af94Brad Fitzpatrick}
102