blob: eb7c26a28e376e7b6fc79fe60e5fe8954357d7b6 [file] [log] [blame]
Joe Onorato9c1289c2009-08-17 11:03:03 -04001/*
2 * Copyright (C) 2008 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
Daniel Sandler325dc232013-06-05 22:57:57 -040017package com.android.launcher3;
Joe Onorato9c1289c2009-08-17 11:03:03 -040018
19import android.os.Handler;
20import android.os.Looper;
21import android.os.Message;
22import android.os.MessageQueue;
Winson Chung81b52252012-08-27 15:34:29 -070023import android.util.Pair;
Michael Jurka34c2e6c2013-12-13 16:07:45 +010024
Adam Cohen091440a2015-03-18 14:16:05 -070025import com.android.launcher3.util.Thunk;
26
Winson Chung81b52252012-08-27 15:34:29 -070027import java.util.LinkedList;
28import java.util.ListIterator;
Joe Onorato9c1289c2009-08-17 11:03:03 -040029
30/**
31 * Queue of things to run on a looper thread. Items posted with {@link #post} will not
32 * be actually enqued on the handler until after the last one has run, to keep from
33 * starving the thread.
34 *
35 * This class is fifo.
36 */
37public class DeferredHandler {
Adam Cohen091440a2015-03-18 14:16:05 -070038 @Thunk LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>();
Joe Onorato9c1289c2009-08-17 11:03:03 -040039 private MessageQueue mMessageQueue = Looper.myQueue();
40 private Impl mHandler = new Impl();
41
Adam Cohen091440a2015-03-18 14:16:05 -070042 @Thunk class Impl extends Handler implements MessageQueue.IdleHandler {
Joe Onorato9c1289c2009-08-17 11:03:03 -040043 public void handleMessage(Message msg) {
Winson Chung81b52252012-08-27 15:34:29 -070044 Pair<Runnable, Integer> p;
Joe Onorato9c1289c2009-08-17 11:03:03 -040045 Runnable r;
46 synchronized (mQueue) {
Joe Onorato33ed7b22009-09-23 18:20:54 -070047 if (mQueue.size() == 0) {
48 return;
49 }
Winson Chung81b52252012-08-27 15:34:29 -070050 p = mQueue.removeFirst();
51 r = p.first;
Joe Onorato9c1289c2009-08-17 11:03:03 -040052 }
53 r.run();
54 synchronized (mQueue) {
55 scheduleNextLocked();
56 }
57 }
58
59 public boolean queueIdle() {
60 handleMessage(null);
61 return false;
62 }
63 }
64
65 private class IdleRunnable implements Runnable {
66 Runnable mRunnable;
67
68 IdleRunnable(Runnable r) {
69 mRunnable = r;
70 }
71
72 public void run() {
73 mRunnable.run();
74 }
75 }
76
77 public DeferredHandler() {
78 }
79
80 /** Schedule runnable to run after everything that's on the queue right now. */
81 public void post(Runnable runnable) {
Winson Chung81b52252012-08-27 15:34:29 -070082 post(runnable, 0);
83 }
84 public void post(Runnable runnable, int type) {
Joe Onorato9c1289c2009-08-17 11:03:03 -040085 synchronized (mQueue) {
Winson Chung81b52252012-08-27 15:34:29 -070086 mQueue.add(new Pair<Runnable, Integer>(runnable, type));
Joe Onorato9c1289c2009-08-17 11:03:03 -040087 if (mQueue.size() == 1) {
88 scheduleNextLocked();
89 }
90 }
91 }
92
93 /** Schedule runnable to run when the queue goes idle. */
94 public void postIdle(final Runnable runnable) {
Winson Chung81b52252012-08-27 15:34:29 -070095 postIdle(runnable, 0);
96 }
97 public void postIdle(final Runnable runnable, int type) {
98 post(new IdleRunnable(runnable), type);
Joe Onorato9c1289c2009-08-17 11:03:03 -040099 }
100
Daniel Sandlerdca66122010-04-13 16:23:58 -0400101 public void cancelRunnable(Runnable runnable) {
102 synchronized (mQueue) {
103 while (mQueue.remove(runnable)) { }
104 }
105 }
Winson Chung81b52252012-08-27 15:34:29 -0700106 public void cancelAllRunnablesOfType(int type) {
107 synchronized (mQueue) {
108 ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator();
109 Pair<Runnable, Integer> p;
110 while (iter.hasNext()) {
111 p = iter.next();
112 if (p.second == type) {
113 iter.remove();
114 }
115 }
116 }
117 }
Daniel Sandlerdca66122010-04-13 16:23:58 -0400118
Joe Onorato9c1289c2009-08-17 11:03:03 -0400119 public void cancel() {
120 synchronized (mQueue) {
121 mQueue.clear();
122 }
123 }
124
Adam Cohena13a2f22012-07-23 14:29:15 -0700125 /** Runs all queued Runnables from the calling thread. */
126 public void flush() {
Winson Chung81b52252012-08-27 15:34:29 -0700127 LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>();
Adam Cohena13a2f22012-07-23 14:29:15 -0700128 synchronized (mQueue) {
129 queue.addAll(mQueue);
130 mQueue.clear();
131 }
Winson Chung81b52252012-08-27 15:34:29 -0700132 for (Pair<Runnable, Integer> p : queue) {
133 p.first.run();
Adam Cohena13a2f22012-07-23 14:29:15 -0700134 }
135 }
136
Joe Onorato9c1289c2009-08-17 11:03:03 -0400137 void scheduleNextLocked() {
138 if (mQueue.size() > 0) {
Winson Chung81b52252012-08-27 15:34:29 -0700139 Pair<Runnable, Integer> p = mQueue.getFirst();
140 Runnable peek = p.first;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400141 if (peek instanceof IdleRunnable) {
142 mMessageQueue.addIdleHandler(mHandler);
143 } else {
144 mHandler.sendEmptyMessage(1);
145 }
146 }
147 }
148}
149