Merge "Run with scissors." into jb-mr1-dev

This commit is contained in:
Jeff Brown
2012-08-29 15:41:57 -07:00
committed by Android (Google) Code Review

View File

@@ -411,6 +411,50 @@ public class Handler {
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
/**
* Runs the specified task synchronously.
*
* If the current thread is the same as the handler thread, then the runnable
* runs immediately without being enqueued. Otherwise, posts the runnable
* to the handler and waits for it to complete before returning.
*
* This method is dangerous! Improper use can result in deadlocks.
* Never call this method while any locks are held or use it in a
* possibly re-entrant manner.
*
* This method is occasionally useful in situations where a background thread
* must synchronously await completion of a task that must run on the
* handler's thread. However, this problem is often a symptom of bad design.
* Consider improving the design (if possible) before resorting to this method.
*
* One example of where you might want to use this method is when you just
* set up a Handler thread and need to perform some initialization steps on
* it before continuing execution.
*
* @param r The Runnable that will be executed synchronously.
*
* @return Returns true if the Runnable was successfully executed.
* Returns false on failure, usually because the
* looper processing the message queue is exiting.
*
* @hide This method is prone to abuse and should probably not be in the API.
* If we ever do make it part of the API, we might want to rename it to something
* less funny like runUnsafe().
*/
public final boolean runWithScissors(final Runnable r) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this);
}
/**
* Remove any pending posts of Runnable r that are in the message queue.
*/
@@ -678,4 +722,41 @@ public class Handler {
final Callback mCallback;
final boolean mAsynchronous;
IMessenger mMessenger;
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler) {
if (!handler.post(this)) {
return false;
}
synchronized (this) {
while (!mDone) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}
return true;
}
}
}