OK, I've identified the problem:
1) In Geodesics we see:
Geodesic3D(Graphics3D g3d) {
this.g3d = g3d;
if (vertexCounts == null)
initialize();
}
private synchronized void initialize() {
if (vertexCounts != null) {
return;
}
vertexCounts = new short[maxLevel];
.....
}
Fine, this APPEARS to say, "If some other thread has not STARTED to
initialize the geodesic normals system, go ahead and initialize." That's
important, because only the first thread should initialize. Note that
this is not "the first thread from this web page loading" but "the first
thread from any page from this server (or, perhaps, from this server
using this Jar file, I suspect) since the Jmol applet has first been
used in this browser session."
2) It turns out there are two problems with this:
Problem 1: It is NOT "Wait here until some other thread has FINISHED
initializing the geodesci normals system." Miguel is saying, "Oh
[EMAIL PROTECTED]" right now. Because while one thread has STARTED -- but not
FINISHED -- initializing the normals system, another thread has bypassed
initialization and is fast into creating an isosurface that needs that
system.
Problem 2: You (apparently) cannot use synchronization within a
constructor. At least in Firefox (the only browser I tested this on) I
changed the above to this:
Geodesic3D(Graphics3D g3d) {
this.g3d = g3d;
String msg = "Geodesecs "+ System.currentTimeMillis();
System.out.println(msg+" 0");
initialize();
System.out.println(msg+" 1");
}
private synchronized void initialize() {
System.out.println("geodesic init");
if (vertexCounts != null) {
System.out.println("geodesic init skipped");
return;
}
System.out.println("geodesic init continuing");
vertexCounts = new short[maxLevel];
...
for(int i=0;i++<1000000;){String s="";} // just to slow it down
System.out.println("geodesic init 1");
}
Now, you might expect to see the threads wait for the synchronization,
right? But NOOOO! I get for a page displaying eight orbitals [added
comments in brackets]:
Geodesecs 1149943353546 0
Geodesecs 1149943353546 0
Geodesecs 1149943353546 0
Geodesecs 1149943353546 0
Geodesecs 1149943353546 0
Geodesecs 1149943353546 0
[that's six of them]
geodesic init
geodesic init
geodesic init
geodesic init
Geodesecs 1149943353546 0
geodesic init
geodesic init
[how can this be -- they are synchronized, no? Ah, but they are
CONSTRUCTORS!]
geodesic init continuing
geodesic init continuing
geodesic init continuing
geodesic init continuing
[you're kidding, right? ALL continuing? What happened to the sync?]
geodesic init
geodesic init continuing
geodesic init continuing
[#$&[EMAIL PROTECTED]
geodesic init 1
[at this point 7 contructors have started, 7 have started into
initialize() in full, 5 are CONTINUING, one has completed initialize();
one is unaccounted for, and none have finished construction of Geodesics.]
Could not instantiate wrappedApplet classorg.jmol.applet.Jmol
java.lang.NullPointerException
at org.jmol.g3d.Geodesic3D.getVertex(Geodesic3D.java:406)
at org.jmol.g3d.Geodesic3D.quadruple(Geodesic3D.java:296)
at org.jmol.g3d.Geodesic3D.initialize(Geodesic3D.java:216)
at org.jmol.g3d.Geodesic3D.<init>(Geodesic3D.java:180)
at org.jmol.g3d.Graphics3D.<init>(Graphics3D.java:104)
at org.jmol.viewer.Viewer.<init>(Viewer.java:121)
at org.jmol.viewer.Viewer.allocateViewer(Viewer.java:143)
at org.jmol.api.JmolViewer.allocateViewer(JmolViewer.java:51)
at org.jmol.applet.Jmol.initWindows(Jmol.java:182)
at org.jmol.applet.Jmol.init(Jmol.java:145)
at
org.jmol.appletwrapper.WrappedAppletLoader.run(WrappedAppletLoader.java:51)
[There it is!!! No surprise here, I guess.]
geodesic init 1
geodesic init skipped
geodesic init 1
geodesic init 1
[3 more have done the FULL initialization; one did skip]
Geodesecs 1149943353546 1
Geodesecs 1149943353546 1
Geodesecs 1149943353671 0
Geodesecs 1149943353546 1
Geodesecs 1149943353546 1
[ok, the first 4 threads have completed construction of Geodesics; #8 is
finally getting going]
Could not instantiate wrappedApplet classorg.jmol.applet.Jmol
java.lang.NullPointerException
at org.jmol.g3d.Geodesic3D.getVertex(Geodesic3D.java:406)
at org.jmol.g3d.Geodesic3D.quadruple(Geodesic3D.java:295)
at org.jmol.g3d.Geodesic3D.initialize(Geodesic3D.java:216)
at org.jmol.g3d.Geodesic3D.<init>(Geodesic3D.java:180)
at org.jmol.g3d.Graphics3D.<init>(Graphics3D.java:104)
at org.jmol.viewer.Viewer.<init>(Viewer.java:121)
at org.jmol.viewer.Viewer.allocateViewer(Viewer.java:143)
at org.jmol.api.JmolViewer.allocateViewer(JmolViewer.java:51)
at org.jmol.applet.Jmol.initWindows(Jmol.java:182)
at org.jmol.applet.Jmol.init(Jmol.java:145)
at
org.jmol.appletwrapper.WrappedAppletLoader.run(WrappedAppletLoader.java:51)
[argh!]
geodesic init
geodesic init skipped
Geodesecs 1149943353671 1
[#8 skips all initialization]
Geodesecs 1149943353546 1
[six completions; two errors; page shows orbitals 1,2,3,4,5, and 7, but
not 6 or 8]
THAT's the problem. I leave it to Miguel to tell us the elegant
solution. Mine is a classic no-synchronize entry/exit flag system using
a static boolean array:
Geodesic3D(Graphics3D g3d) {
this.g3d = g3d;
String msg = "Geodesecs "+ System.currentTimeMillis();
System.out.println(msg+" 0");
initialize();
System.out.println(msg+" 1");
}
static Point3i testInit = new Point3i();
private void initialize() {
System.out.println("geodesic init " + testInit + " started");
if (testInit.x++ > 0 && testInit.y == 0) {
while (testInit.y == 0) {
try{
Thread.sleep(10);
} catch(Exception e) {
System.out.println("geodesic error "+e);
}
System.out.println("geodesic init "+ testInit + " waiting");
}
System.out.println("geodesic init skipped");
return;
}
System.out.println("geodesic init " + testInit + " continuing");
...
System.out.println("geodesic init " + testInit + " completed");
++testInit.y;
}
Note that this takes advantage of the fact that Point3i is an object
that allows storage of two values and that, though static, allows for
the modification of these values. I'm just using testInit.x and
testInit.y. I now get:
Geodesecs 1149949067812 0
geodesic init (0, 0, 0) started
geodesic init (1, 0, 0) continuing
Geodesecs 1149949067843 0
geodesic init (1, 0, 0) started
Geodesecs 1149949067843 0
geodesic init (2, 0, 0) started
Geodesecs 1149949067843 0
geodesic init (3, 0, 0) started
Geodesecs 1149949067843 0
geodesic init (4, 0, 0) started
Geodesecs 1149949067843 0
geodesic init (5, 0, 0) started
geodesic init (6, 0, 0) waiting
geodesic init (6, 0, 0) waiting
geodesic init (6, 0, 0) waiting
geodesic init (6, 0, 0) waiting
Geodesecs 1149949067843 0
geodesic init (6, 0, 0) started
geodesic init (7, 0, 0) waiting
Geodesecs 1149949067843 0
geodesic init (7, 0, 0) started
geodesic init (8, 0, 0) completed
Geodesecs 1149949067812 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
geodesic init (8, 1, 0) waiting
geodesic init skipped
Geodesecs 1149949067843 1
That's it! I see 8 orbitals now, and only one full initialization.
No synchronization.
Comments?
Bob
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers