summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/MessageQueue.java123
1 files changed, 54 insertions, 69 deletions
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 2813863..6237c0e 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -33,6 +33,7 @@ import java.util.ArrayList;
public class MessageQueue {
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
+ private IdleHandler[] mPendingIdleHandlers;
private boolean mQuiting = false;
boolean mQuitAllowed = true;
@@ -105,90 +106,74 @@ public class MessageQueue {
}
final Message next() {
- boolean tryIdle = true;
- // when we start out, we'll just touch the input pipes and then go from there
- int timeToNextEventMillis = 0;
+ int pendingIdleHandlerCount = -1; // -1 only during first iteration
+ int nextPollTimeoutMillis = 0;
- while (true) {
- long now;
- Object[] idlers = null;
-
- boolean dispatched = nativePollOnce(timeToNextEventMillis);
+ for (;;) {
+ if (nextPollTimeoutMillis != 0) {
+ Binder.flushPendingCommands();
+ }
+ nativePollOnce(nextPollTimeoutMillis);
- // Try to retrieve the next message, returning if found.
synchronized (this) {
- now = SystemClock.uptimeMillis();
- Message msg = pullNextLocked(now);
+ // Try to retrieve the next message. Return if found.
+ final long now = SystemClock.uptimeMillis();
+ final Message msg = mMessages;
if (msg != null) {
- return msg;
+ final long when = msg.when;
+ if (now >= when) {
+ mMessages = msg.next;
+ if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
+ return msg;
+ } else {
+ nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
+ }
+ } else {
+ nextPollTimeoutMillis = -1;
+ }
+
+ // If first time, then get the number of idlers to run.
+ if (pendingIdleHandlerCount < 0) {
+ pendingIdleHandlerCount = mIdleHandlers.size();
}
-
- if (tryIdle && mIdleHandlers.size() > 0) {
- idlers = mIdleHandlers.toArray();
+ if (pendingIdleHandlerCount == 0) {
+ // No idle handlers to run. Loop and wait some more.
+ continue;
}
- }
-
- // There was no message so we are going to wait... but first,
- // if there are any idle handlers let them know.
- boolean didIdle = false;
- if (idlers != null) {
- for (Object idler : idlers) {
- boolean keep = false;
- try {
- didIdle = true;
- keep = ((IdleHandler)idler).queueIdle();
- } catch (Throwable t) {
- Log.wtf("MessageQueue", "IdleHandler threw exception", t);
- }
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler);
- }
- }
+ if (mPendingIdleHandlers == null) {
+ mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
- }
-
- // While calling an idle handler, a new message could have been
- // delivered... so go back and look again for a pending message.
- if (didIdle) {
- tryIdle = false;
- continue;
+ mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
- synchronized (this) {
- // No messages, nobody to tell about it... time to wait!
- if (mMessages != null) {
- long longTimeToNextEventMillis = mMessages.when - now;
-
- if (longTimeToNextEventMillis > 0) {
- Binder.flushPendingCommands();
- timeToNextEventMillis = (int) Math.min(longTimeToNextEventMillis,
- Integer.MAX_VALUE);
- } else {
- timeToNextEventMillis = 0;
+ // Run the idle handlers.
+ // We only ever reach this code block during the first iteration.
+ for (int i = 0; i < pendingIdleHandlerCount; i++) {
+ final IdleHandler idler = mPendingIdleHandlers[i];
+ mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+ boolean keep = false;
+ try {
+ keep = idler.queueIdle();
+ } catch (Throwable t) {
+ Log.wtf("MessageQueue", "IdleHandler threw exception", t);
+ }
+
+ if (!keep) {
+ synchronized (this) {
+ mIdleHandlers.remove(idler);
}
- } else {
- Binder.flushPendingCommands();
- timeToNextEventMillis = -1;
}
}
- // loop to the while(true) and do the appropriate nativeWait(when)
- }
- }
- final Message pullNextLocked(long now) {
- Message msg = mMessages;
- if (msg != null) {
- if (now >= msg.when) {
- mMessages = msg.next;
- if (Config.LOGV) Log.v(
- "MessageQueue", "Returning message: " + msg);
- return msg;
- }
- }
+ // Reset the idle handler count to 0 so we do not run them again.
+ pendingIdleHandlerCount = 0;
- return null;
+ // While calling an idle handler, a new message could have been delivered
+ // so go back and look again for a pending message without waiting.
+ nextPollTimeoutMillis = 0;
+ }
}
final boolean enqueueMessage(Message msg, long when) {