Bug 1062377 - Rewrite GeckoBackgroundThread to not wait for thread start if possible; r=rnewman

When GeckoBackgroundThread is first used, it starts a new thread and waits for a Handler. This can delay startup. Instead, we can just save the Runnable and run it when the thread is starting.
This commit is contained in:
Jim Chen 2014-09-30 18:19:25 -04:00
Родитель 12d7d71d8f
Коммит 18d2c2ded2
1 изменённых файлов: 45 добавлений и 24 удалений

Просмотреть файл

@ -12,44 +12,65 @@ import java.util.concurrent.SynchronousQueue;
final class GeckoBackgroundThread extends Thread { final class GeckoBackgroundThread extends Thread {
private static final String LOOPER_NAME = "GeckoBackgroundThread"; private static final String LOOPER_NAME = "GeckoBackgroundThread";
// Guarded by 'this'. // Guarded by 'GeckoBackgroundThread.class'.
private static Handler sHandler; private static Handler handler;
private SynchronousQueue<Handler> mHandlerQueue = new SynchronousQueue<Handler>(); private static Thread thread;
// The initial Runnable to run on the new thread. Its purpose
// is to avoid us having to wait for the new thread to start.
private Runnable initialRunnable;
// Singleton, so private constructor. // Singleton, so private constructor.
private GeckoBackgroundThread() { private GeckoBackgroundThread(final Runnable initialRunnable) {
super(); this.initialRunnable = initialRunnable;
} }
@Override @Override
public void run() { public void run() {
setName(LOOPER_NAME); setName(LOOPER_NAME);
Looper.prepare(); Looper.prepare();
try {
mHandlerQueue.put(new Handler()); synchronized (GeckoBackgroundThread.class) {
} catch (InterruptedException ie) {} handler = new Handler();
GeckoBackgroundThread.class.notify();
}
if (initialRunnable != null) {
initialRunnable.run();
initialRunnable = null;
}
Looper.loop(); Looper.loop();
} }
// Get a Handler for a looper thread, or create one if it doesn't yet exist. private static void startThread(final Runnable initialRunnable) {
/*package*/ static synchronized Handler getHandler() { thread = new GeckoBackgroundThread(initialRunnable);
if (sHandler == null) { ThreadUtils.setBackgroundThread(thread);
GeckoBackgroundThread lt = new GeckoBackgroundThread();
ThreadUtils.setBackgroundThread(lt); thread.setDaemon(true);
lt.start(); thread.start();
try {
sHandler = lt.mHandlerQueue.take();
} catch (InterruptedException ie) {}
}
return sHandler;
} }
/*package*/ static void post(Runnable runnable) { // Get a Handler for a looper thread, or create one if it doesn't yet exist.
Handler handler = getHandler(); /*package*/ static synchronized Handler getHandler() {
if (handler == null) { if (thread == null) {
throw new IllegalStateException("No handler! Must have been interrupted. Not posting."); startThread(null);
} }
handler.post(runnable);
while (handler == null) {
try {
GeckoBackgroundThread.class.wait();
} catch (final InterruptedException e) {
}
}
return handler;
}
/*package*/ static synchronized void post(final Runnable runnable) {
if (thread == null) {
startThread(runnable);
return;
}
getHandler().post(runnable);
} }
} }