I'm launching my application, which is derived from SimpleGame, from a swing interface, in a new Thread (with the overloaded run() doing the starting).
If I try to show the properties box (via setConfigShowMode(ConfigShowMode.AlwaysShow) ), everything hangs.
I think I've located the issue, but my limited knowledge in concurrency wasn't enough to fix it (and I have tried :// ). The hang occurs when creating an LWJGLPropertiesDialog object:
// from com.jme.system.lwjgl.LWJGLPropertiesDialog
public LWJGLPropertiesDialog(GameSettings source, URL imageFile, Stack<Runnable> mainThreadTasks) {
if (null == source)
throw new JmeException("PropertyIO source cannot be null");
this.source = source;
this.imageFile = imageFile;
this.mainThreadTasks = mainThreadTasks;
ModesRetriever retrieval = new ModesRetriever(); // A runnable object
if ( mainThreadTasks != null )
{
mainThreadTasks.add(retrieval);
}
else
{
retrieval.run();
}
modes = retrieval.getModes();
Arrays.sort(modes, new DisplayModeSorter());
createUI();
}
This is called from AbstractGame's getAttributes method, and the mainThreadTasks stack is not null. So the retrieval task is added to the stack, and then retrieval.getModes() is called, which is what hangs:
// from com.jme.system.lwjgl.LWJGLPropertiesDialog.ModesRetriever
public DisplayMode[] getModes() {
while (!this.ready) {
try {
Thread.sleep(10);
} catch (Exception e) { }
}
return modes;
}
The "ready" variable was supposed to be set to true by the following piece of code:
// from com.jme.system.lwjgl.LWJGLPropertiesDialog.ModesRetriever
public void run() {
try {
modes = Display.getAvailableDisplayModes();
} catch (LWJGLException e) {
logger.logp(Level.SEVERE, this.getClass().toString(),
"LWJGLPropertiesDialog(GameSettings, URL)", "Exception", e);
return;
}
ready = true;
}
which is never actually being run (AbstractGame would have called this later, but the application never gets past the retrieval.getModes() line, so AbstractGame never gets around to it). So I guess the problem is sort of that AbstractGame expects the object to finish constructing, but that can only be done when AbstractGame starts running Runnables from the stack :-o (I tried to make a little post-initialization method with the last 3 lines from the constructor, and calling it from AbstractGame after it starts running the mainThreadTasks; this got a window on screen that wouldn't update and showed no controls; this is where I got really confused, and figured I didn't know enough to fix this).
If a small test is needed to verify, I'll make one later, though I think the code sort of gives away that there is in fact a problem.
I've currently coded around this by setting setConfigShowMode(ConfigShowMode.NeverShow), creating an LWJGLPropertiesDialog, and adding a listener to it that opens my application when the properties window closes (via "ok").
So perhaps someone with more knowledge in concurrency is willing to take a shot a this...