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:
@@ -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,90 +106,74 @@ 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) {
|
||||||
return msg;
|
final long when = msg.when;
|
||||||
}
|
if (now >= when) {
|
||||||
|
mMessages = msg.next;
|
||||||
if (tryIdle && mIdleHandlers.size() > 0) {
|
if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
|
||||||
idlers = mIdleHandlers.toArray();
|
return msg;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
timeToNextEventMillis = 0;
|
nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Binder.flushPendingCommands();
|
nextPollTimeoutMillis = -1;
|
||||||
timeToNextEventMillis = -1;
|
}
|
||||||
|
|
||||||
|
// If first time, then get the number of idlers to run.
|
||||||
|
if (pendingIdleHandlerCount < 0) {
|
||||||
|
pendingIdleHandlerCount = mIdleHandlers.size();
|
||||||
|
}
|
||||||
|
if (pendingIdleHandlerCount == 0) {
|
||||||
|
// No idle handlers to run. Loop and wait some more.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPendingIdleHandlers == null) {
|
||||||
|
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
|
||||||
|
}
|
||||||
|
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// loop to the while(true) and do the appropriate nativeWait(when)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Message pullNextLocked(long now) {
|
// Reset the idle handler count to 0 so we do not run them again.
|
||||||
Message msg = mMessages;
|
pendingIdleHandlerCount = 0;
|
||||||
if (msg != null) {
|
|
||||||
if (now >= msg.when) {
|
|
||||||
mMessages = msg.next;
|
|
||||||
if (Config.LOGV) Log.v(
|
|
||||||
"MessageQueue", "Returning message: " + msg);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
final boolean enqueueMessage(Message msg, long when) {
|
||||||
|
|||||||
Reference in New Issue
Block a user