summaryrefslogtreecommitdiff
path: root/core/java/android/os/MessageQueue.java
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-10-05 15:35:37 -0700
committerJeff Brown <jeffbrown@google.com>2010-10-07 13:26:39 -0700
commit415d8c38199e258dfce92cdb0c69e056b3b51ef8 (patch)
tree5bf6d167a19b272f2a153df6010a7dd6f58a274f /core/java/android/os/MessageQueue.java
parent930d6c3cd5ad387489eb1d35a38beeafe54166b6 (diff)
Switch Looper back to using poll() instead of epoll().
Added a couple of micro-optimizations to avoid calling wake() unnecessarily and reduce JNI overhead slightly. Fixed a minor issue where we were not clearing the "next" field of Messages returned by the MessageQueue so the Message would hold on to its successor and potentially prevent the GC from collecting it if the message were leaked somehow. Change-Id: I488d29417ce0cdd7d0e447cda76ec978ef7f811c
Diffstat (limited to 'core/java/android/os/MessageQueue.java')
-rw-r--r--core/java/android/os/MessageQueue.java21
1 files changed, 16 insertions, 5 deletions
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 6237c0e4e523..009017753ed3 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -34,16 +34,19 @@ public class MessageQueue {
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
private IdleHandler[] mPendingIdleHandlers;
- private boolean mQuiting = false;
+ private boolean mQuiting;
boolean mQuitAllowed = true;
+ // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
+ private boolean mBlocked;
+
@SuppressWarnings("unused")
private int mPtr; // used by native code
private native void nativeInit();
private native void nativeDestroy();
- private native boolean nativePollOnce(int timeoutMillis);
- private native void nativeWake();
+ private native void nativePollOnce(int ptr, int timeoutMillis);
+ private native void nativeWake(int ptr);
/**
* Callback interface for discovering when a thread is going to block
@@ -113,7 +116,7 @@ public class MessageQueue {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
- nativePollOnce(nextPollTimeoutMillis);
+ nativePollOnce(mPtr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
@@ -122,7 +125,9 @@ public class MessageQueue {
if (msg != null) {
final long when = msg.when;
if (now >= when) {
+ mBlocked = false;
mMessages = msg.next;
+ msg.next = null;
if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
} else {
@@ -138,6 +143,7 @@ public class MessageQueue {
}
if (pendingIdleHandlerCount == 0) {
// No idle handlers to run. Loop and wait some more.
+ mBlocked = true;
continue;
}
@@ -184,6 +190,7 @@ public class MessageQueue {
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
+ final boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
@@ -200,6 +207,7 @@ public class MessageQueue {
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
+ needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
@@ -208,9 +216,12 @@ public class MessageQueue {
}
msg.next = prev.next;
prev.next = msg;
+ needWake = false; // still waiting on head, no need to wake up
}
}
- nativeWake();
+ if (needWake) {
+ nativeWake(mPtr);
+ }
return true;
}