OK, I've discovered the problem and propose a solution.
BACKGROUND -- How Jmol waits
--------------------------------------
At the beginning of every script and at key points (moveTo, delay,
refresh, for example) a repaintManager.requestRepaintAndWait() is
carried out:
class RepaintManager:
synchronized void requestRepaintAndWait() {
viewer.awtComponent.repaint();
try {
wait();
} catch (InterruptedException e) {
}
}
If I understand this correctly, this is simply a way to trigger the
repaint event from the OS. The event queue thread runs the app/applet
paint() event, which starts the rendering. After rendering, the last
thing Viewer.renderScreenImage() does is call repaintManager.repaintView():
class RepaintManager:
synchronized void repaintView() {
repaintPending = false;
notify(); // to cancel any wait
}
OK, so the function of that notify() is to restart the thread that is
waiting in requestRepaintAndWait(). The notify() terminates the wait().
THE PROBLEM - using the wrong thread
------------------------------------------
The problem is this. If you execute
viewer.scriptWait()
from a user event, then the thread that is running it is the event queue
thread, because it is that same thread that does all the event handling.
So it is the event queue thread that is waiting. Ah, but if the event
queue thread is waiting, the event queue thread cannot produce the
trigger that will ultimately deliver the notify(), and the ship is sunk.
THE SOLUTION - use a different thread
------------------------------------------
In the Jmol application code that I just committed what I did is to have
the button action listener NOT execute executeCommand(), which calls
scriptWait(). Rather, the button action listener just starts a new
thread of the class ExecutionCommandThread. It is THIS thread then that
waits. The event queue thread goes on its merry way. Here's my code.
executeCommmandAsThread() is called by the button action listener.
class ScriptWindow:
ExecuteCommandThread execThread;
void executeCommandAsThread(){
String strCommand = console.getCommandString().trim();
if (strCommand.length() > 0) {
execThread = new ExecuteCommandThread(strCommand);
execThread.start();
}
}
class ExecuteCommandThread extends Thread {
String strCommand;
ExecuteCommandThread (String command) {
strCommand = command;
}
public void run() {
try {
executeCommand(strCommand);
} catch (Exception ie) {
Logger.debug("execution command interrupted!"+ie);
}
}
}
There's proabably a more elegant way of doing this, but for now that's
how it works.
SO: If you want to use scriptWait():
1) first, I recommend instead a new method I've added,
Object Viewer.scriptWaitStatus(String returnType, String script,
String statusList)
What this function does is to run the script, and follow whatever status
information you might be interested in knowing about.
These are the items listed at
http://www.stolaf.edu/people/hansonr/jmol/docs/?ver=11.0#statusreporting
The returnType parameter is one of "JSON", "String", "readable", or
"object". What would be interesting to this crowd is "object"
because it returns a Vector of Vectors of Vectors:
* info = [ statusRecortSet0, statusRecortSet1,
statusRecortSet2, ...]
* statusRecordSet = [ statusRecord0, statusRecord1,
statusRecord2, ...]
* statusRecord = [int msgPtr, String statusName, int intInfo,
String msg]
This allows for parsing of the different record types independently, and
sorting them overall if desired (on the msgPtr).
2) Just make sure that the thread that is using scriptWait() is NOT the
event queue thread. Basically, start a new thread with any response to a
user event. Or set up a running event queue thread that processes the
commands in order of appearance if they are coming from a user. (This is
probably what we should do for the applet as well.)
Comments?
Bob
Andreas Prlic wrote:
>>If others can suggest the "right" way to do this, that would be
>>welcome.
>>How is this sort of thing supposed to be handled?
>>
>>
>
>hm. this is not easy....
> - but I would be very interested in getting this fixed and would be
>willing to help ...
>
>I guess all the Evals should go through a common queue ...
>
>Andreas
>
>-----------------------------------------------------------------------
>
>Andreas Prlic Wellcome Trust Sanger Institute
> Hinxton, Cambridge CB10 1SA, UK
> +44 (0) 1223 49 6891
>
>
>-------------------------------------------------------------------------
>Take Surveys. Earn Cash. Influence the Future of IT
>Join SourceForge.net's Techsay panel and you'll get the chance to share your
>opinions on IT & business topics through brief surveys -- and earn cash
>http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
>_______________________________________________
>Jmol-developers mailing list
>[email protected]
>https://lists.sourceforge.net/lists/listinfo/jmol-developers
>
>
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers