am ed739327: Simplify and optimize MessageQueue loop.

Merge commit 'ed7393274af2f268fcdede5f1a3d72c9af842b8e' into gingerbread-plus-aosp

* commit 'ed7393274af2f268fcdede5f1a3d72c9af842b8e':
  Simplify and optimize MessageQueue loop.
This commit is contained in:
Jeff Brown
2010-09-21 15:59:14 -07:00
committed by Android Git Automerger

View File

@@ -33,6 +33,7 @@ import java.util.ArrayList;
public class MessageQueue { public class MessageQueue {
Message mMessages; Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>(); private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
private IdleHandler[] mPendingIdleHandlers;
private boolean mQuiting = false; private boolean mQuiting = false;
boolean mQuitAllowed = true; boolean mQuitAllowed = true;
@@ -105,38 +106,56 @@ public class MessageQueue {
} }
final Message next() { final Message next() {
boolean tryIdle = true; int pendingIdleHandlerCount = -1; // -1 only during first iteration
// when we start out, we'll just touch the input pipes and then go from there int nextPollTimeoutMillis = 0;
int timeToNextEventMillis = 0;
while (true) { for (;;) {
long now; if (nextPollTimeoutMillis != 0) {
Object[] idlers = null; Binder.flushPendingCommands();
}
nativePollOnce(nextPollTimeoutMillis);
boolean dispatched = nativePollOnce(timeToNextEventMillis);
// Try to retrieve the next message, returning if found.
synchronized (this) { synchronized (this) {
now = SystemClock.uptimeMillis(); // Try to retrieve the next message. Return if found.
Message msg = pullNextLocked(now); final long now = SystemClock.uptimeMillis();
final Message msg = mMessages;
if (msg != null) { if (msg != null) {
final long when = msg.when;
if (now >= when) {
mMessages = msg.next;
if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
return msg; return msg;
} else {
nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
}
} else {
nextPollTimeoutMillis = -1;
} }
if (tryIdle && mIdleHandlers.size() > 0) { // If first time, then get the number of idlers to run.
idlers = mIdleHandlers.toArray(); if (pendingIdleHandlerCount < 0) {
pendingIdleHandlerCount = mIdleHandlers.size();
} }
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 (mPendingIdleHandlers == null) {
// if there are any idle handlers let them know. mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
boolean didIdle = false; }
if (idlers != null) { mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
for (Object idler : idlers) { }
// 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; boolean keep = false;
try { try {
didIdle = true; keep = idler.queueIdle();
keep = ((IdleHandler)idler).queueIdle();
} catch (Throwable t) { } catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t); Log.wtf("MessageQueue", "IdleHandler threw exception", t);
} }
@@ -147,48 +166,14 @@ public class MessageQueue {
} }
} }
} }
}
// While calling an idle handler, a new message could have been // Reset the idle handler count to 0 so we do not run them again.
// delivered... so go back and look again for a pending message. pendingIdleHandlerCount = 0;
if (didIdle) {
tryIdle = false;
continue;
}
synchronized (this) { // While calling an idle handler, a new message could have been delivered
// No messages, nobody to tell about it... time to wait! // so go back and look again for a pending message without waiting.
if (mMessages != null) { nextPollTimeoutMillis = 0;
long longTimeToNextEventMillis = mMessages.when - now;
if (longTimeToNextEventMillis > 0) {
Binder.flushPendingCommands();
timeToNextEventMillis = (int) Math.min(longTimeToNextEventMillis,
Integer.MAX_VALUE);
} else {
timeToNextEventMillis = 0;
} }
} 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;
}
}
return null;
} }
final boolean enqueueMessage(Message msg, long when) { final boolean enqueueMessage(Message msg, long when) {