blob: 92ecf964388c259c826559eccb6c2f589e386d88 [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;
24import java.util.LinkedList;
25import java.util.ListIterator;
Joe Onorato9c1289c2009-08-17 11:03:03 -040026
27/**
28 * Queue of things to run on a looper thread. Items posted with {@link #post} will not
29 * be actually enqued on the handler until after the last one has run, to keep from
30 * starving the thread.
31 *
32 * This class is fifo.
33 */
34public class DeferredHandler {
Winson Chung81b52252012-08-27 15:34:29 -070035 private LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>();
Joe Onorato9c1289c2009-08-17 11:03:03 -040036 private MessageQueue mMessageQueue = Looper.myQueue();
37 private Impl mHandler = new Impl();
38
39 private class Impl extends Handler implements MessageQueue.IdleHandler {
40 public void handleMessage(Message msg) {
Winson Chung81b52252012-08-27 15:34:29 -070041 Pair<Runnable, Integer> p;
Joe Onorato9c1289c2009-08-17 11:03:03 -040042 Runnable r;
43 synchronized (mQueue) {
Joe Onorato33ed7b22009-09-23 18:20:54 -070044 if (mQueue.size() == 0) {
45 return;
46 }
Winson Chung81b52252012-08-27 15:34:29 -070047 p = mQueue.removeFirst();
48 r = p.first;
Joe Onorato9c1289c2009-08-17 11:03:03 -040049 }
50 r.run();
51 synchronized (mQueue) {
52 scheduleNextLocked();
53 }
54 }
55
56 public boolean queueIdle() {
57 handleMessage(null);
58 return false;
59 }
60 }
61
62 private class IdleRunnable implements Runnable {
63 Runnable mRunnable;
64
65 IdleRunnable(Runnable r) {
66 mRunnable = r;
67 }
68
69 public void run() {
70 mRunnable.run();
71 }
72 }
73
74 public DeferredHandler() {
75 }
76
77 /** Schedule runnable to run after everything that's on the queue right now. */
78 public void post(Runnable runnable) {
Winson Chung81b52252012-08-27 15:34:29 -070079 post(runnable, 0);
80 }
81 public void post(Runnable runnable, int type) {
Joe Onorato9c1289c2009-08-17 11:03:03 -040082 synchronized (mQueue) {
Winson Chung81b52252012-08-27 15:34:29 -070083 mQueue.add(new Pair<Runnable, Integer>(runnable, type));
Joe Onorato9c1289c2009-08-17 11:03:03 -040084 if (mQueue.size() == 1) {
85 scheduleNextLocked();
86 }
87 }
88 }
89
90 /** Schedule runnable to run when the queue goes idle. */
91 public void postIdle(final Runnable runnable) {
Winson Chung81b52252012-08-27 15:34:29 -070092 postIdle(runnable, 0);
93 }
94 public void postIdle(final Runnable runnable, int type) {
95 post(new IdleRunnable(runnable), type);
Joe Onorato9c1289c2009-08-17 11:03:03 -040096 }
97
Daniel Sandlerdca66122010-04-13 16:23:58 -040098 public void cancelRunnable(Runnable runnable) {
99 synchronized (mQueue) {
100 while (mQueue.remove(runnable)) { }
101 }
102 }
Winson Chung81b52252012-08-27 15:34:29 -0700103 public void cancelAllRunnablesOfType(int type) {
104 synchronized (mQueue) {
105 ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator();
106 Pair<Runnable, Integer> p;
107 while (iter.hasNext()) {
108 p = iter.next();
109 if (p.second == type) {
110 iter.remove();
111 }
112 }
113 }
114 }
Daniel Sandlerdca66122010-04-13 16:23:58 -0400115
Joe Onorato9c1289c2009-08-17 11:03:03 -0400116 public void cancel() {
117 synchronized (mQueue) {
118 mQueue.clear();
119 }
120 }
121
Adam Cohena13a2f22012-07-23 14:29:15 -0700122 /** Runs all queued Runnables from the calling thread. */
123 public void flush() {
Winson Chung81b52252012-08-27 15:34:29 -0700124 LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>();
Adam Cohena13a2f22012-07-23 14:29:15 -0700125 synchronized (mQueue) {
126 queue.addAll(mQueue);
127 mQueue.clear();
128 }
Winson Chung81b52252012-08-27 15:34:29 -0700129 for (Pair<Runnable, Integer> p : queue) {
130 p.first.run();
Adam Cohena13a2f22012-07-23 14:29:15 -0700131 }
132 }
133
Joe Onorato9c1289c2009-08-17 11:03:03 -0400134 void scheduleNextLocked() {
135 if (mQueue.size() > 0) {
Winson Chung81b52252012-08-27 15:34:29 -0700136 Pair<Runnable, Integer> p = mQueue.getFirst();
137 Runnable peek = p.first;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400138 if (peek instanceof IdleRunnable) {
139 mMessageQueue.addIdleHandler(mHandler);
140 } else {
141 mHandler.sendEmptyMessage(1);
142 }
143 }
144 }
145}
146