Removes the threading from SuperDevListener.
This is causing multi-threading issues with compiler
as it does have un-syncrhonized static state.
I couldn't observe any performance difference above the noise level
while testing this with Hello sample app and GWT source.
In single thread I was getting consistently 19 seconds while I was
getting 18.5 to 19+ seconds with the extra thread. Besides this is
the DevMode launch time so even a few seconds shouldn't matter
much.
Bug: issue 9055
Change-Id: I5384904df9d108ae736b6ce0455b90dfaa6e0c63
diff --git a/dev/core/src/com/google/gwt/dev/DevMode.java b/dev/core/src/com/google/gwt/dev/DevMode.java
index 760dec4..6d0499c 100644
--- a/dev/core/src/com/google/gwt/dev/DevMode.java
+++ b/dev/core/src/com/google/gwt/dev/DevMode.java
@@ -513,28 +513,13 @@
+ module.getCanonicalName() + "'");
link(loadLogger, module);
}
-
} catch (UnableToCompleteException e) {
// Already logged.
return false;
} finally {
slowStartupEvent.end();
}
-
- // When in GWTTestCase and not using Dev Mode, there is no listener.
- if (listener == null) {
- return true;
- }
-
- // When this methods exits, the buttons will be enabled in the Swing UI.
- // We shouldn't do that until the code server is ready, or the user might
- // see a blank page.
- try {
- listener.waitUntilReady(getTopLogger());
- return true;
- } catch (UnableToCompleteException e) {
- return false; // already logged
- }
+ return true;
}
@Override
diff --git a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
index 3081041..e727c5c 100644
--- a/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
+++ b/dev/core/src/com/google/gwt/dev/shell/BrowserListener.java
@@ -210,9 +210,4 @@
listenThread.start();
}
}
-
- @Override
- public void waitUntilReady(TreeLogger logger) throws UnableToCompleteException {
- // already ready when constructor returns.
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/shell/CodeServerListener.java b/dev/core/src/com/google/gwt/dev/shell/CodeServerListener.java
index a9914ba..6432fdc 100644
--- a/dev/core/src/com/google/gwt/dev/shell/CodeServerListener.java
+++ b/dev/core/src/com/google/gwt/dev/shell/CodeServerListener.java
@@ -13,7 +13,6 @@
*/
package com.google.gwt.dev.shell;
-import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
@@ -32,17 +31,11 @@
int getSocketPort();
/**
- * Starts the code server. (It won't be ready until the {@link #waitUntilReady returns.)
+ * Starts the code server.
*/
void start();
/**
- * Blocks until the code server ready to handle requests.
- * @throws UnableToCompleteException if unable to start.
- */
- void waitUntilReady(TreeLogger logger) throws UnableToCompleteException;
-
- /**
* Returns the URL to use in the browser for using this codeserver.
*/
URL makeStartupUrl(String url) throws UnableToCompleteException;
diff --git a/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java b/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java
index d266e2a..03fe2d4 100644
--- a/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java
+++ b/dev/core/src/com/google/gwt/dev/shell/SuperDevListener.java
@@ -24,9 +24,9 @@
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.util.arg.OptionJsInteropMode;
import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode;
+import com.google.gwt.thirdparty.guava.common.base.Stopwatch;
import com.google.gwt.thirdparty.guava.common.collect.ListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
-import com.google.gwt.thirdparty.guava.common.util.concurrent.SettableFuture;
import java.io.File;
import java.io.IOException;
@@ -36,17 +36,15 @@
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutionException;
/**
* Starts a superdev-mode codeserver.
*/
public class SuperDevListener implements CodeServerListener {
- private final Thread listenThread;
private final TreeLogger logger;
private final int codeServerPort;
- private final SettableFuture<Void> codeServerReady = SettableFuture.create();
+ private List<String> codeServerArgs;
/**
* Listens for new connections from browsers.
@@ -58,44 +56,7 @@
// This directory must exist when the Code Server starts.
ensureModuleBaseDir(options);
- List<String> args = makeCodeServerArgs(options, codeServerPort);
-
- final String[] codeServerArgs = args.toArray(new String[0]);
-
- logger.log(Type.INFO, "Runing CodeServer with parameters: " + args);
-
- // Using reflection so as we don't create a circular dependency between
- // dev.jar && codeserver.jar
- final Method mainMethod;
- try {
- Class<?> clazz = Class.forName("com.google.gwt.dev.codeserver.CodeServer");
- mainMethod = clazz.getMethod("main", String[].class);
- } catch (ClassNotFoundException e) {
- logger.log(TreeLogger.ERROR, "Unable to find main() method for Super Dev Mode "
- + "code server. Hint: verify that gwt-codeserver.jar is in your classpath.");
- throw new RuntimeException(e);
- } catch (NoSuchMethodException e) {
- logger.log(TreeLogger.ERROR, "Unable to run superdev codeServer.", e);
- throw new RuntimeException(e);
- }
-
- listenThread = new Thread() {
- public void run() {
- try {
- long startTime = System.currentTimeMillis();
- mainMethod.invoke(null, new Object[] {codeServerArgs});
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.log(Type.INFO, "Code server started in " + elapsedTime + " ms");
- // The main method returns when the code server has finished launching.
- codeServerReady.set(null);
- } catch (Exception e) {
- logger.log(TreeLogger.ERROR, "Unable to run superdev codeServer.", e);
- codeServerReady.setException(e);
- }
- }
- };
- listenThread.setName("SuperDevMode code server listener");
- listenThread.setDaemon(true);
+ codeServerArgs = makeCodeServerArgs(options, codeServerPort);
}
@Override
@@ -125,24 +86,31 @@
@Override
public void start() {
- listenThread.start();
+ try {
+ Stopwatch watch = Stopwatch.createStarted();
+ logger.log(Type.INFO, "Runing CodeServer with parameters: " + codeServerArgs);
+ runCodeServer(codeServerArgs.toArray(new String[0]));
+ logger.log(Type.INFO, "Code server started in " + watch + " ms");
+ } catch (Exception e) {
+ logger.log(Type.INFO, "Unable to start Code server");
+ throw new RuntimeException(e);
+ }
}
- @Override
- public void waitUntilReady(TreeLogger logger) throws UnableToCompleteException {
- long startTime = System.currentTimeMillis();
+ private void runCodeServer(String[] mainArgs) throws Exception {
+ // Using reflection so as we don't create a circular dependency between
+ // dev.jar && codeserver.jar
+ Method mainMethod;
try {
- codeServerReady.get();
- } catch (InterruptedException e) {
- logger.log(Type.ERROR, "thread interrupted while waiting for code server");
- throw new UnableToCompleteException();
- } catch (ExecutionException e) {
- logger.log(Type.ERROR, "unable to launch code server", e);
- throw new UnableToCompleteException();
- } finally {
- long elapsedTime = System.currentTimeMillis() - startTime;
- logger.log(Type.INFO, "waited " + elapsedTime + " ms for code server to finish");
+ Class<?> clazz = Class.forName("com.google.gwt.dev.codeserver.CodeServer");
+ mainMethod = clazz.getMethod("main", String[].class);
+ } catch (ClassNotFoundException e) {
+ logger.log(TreeLogger.ERROR, "Unable to find main() method for Super Dev Mode "
+ + "code server. Hint: verify that gwt-codeserver.jar is in your classpath.");
+ throw e;
}
+
+ mainMethod.invoke(null, new Object[] {mainArgs});
}
private static int chooseCodeServerPort(TreeLogger logger, HostedModeOptions options) {