> 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."
Correct.
> 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."
Correct.
> 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.
Not true ... The initialize() method has the keyword 'synchronized'. This
means that only one thread at a time will execute.
The reason that the test (vertexCounts != null) is repeated at the
beginning of initialize() is to make sure that it does not get initialized
twice.
> 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.
That *should not* be the case. 'synchronized' is part of the Java Virtual
Machine and its behavior *should be* well-defined.
> 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?
Correct.
> 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.
Amazing ... I am dumbfounded.
> I leave it to Miguel to tell us the elegant
> solution.
Miguel thought that the current (apparently buggy) implementation was 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?
I will investigate.
It really looks like a JVM bug to me ... but that seems impossible. I will
investigate.
Miguel
_______________________________________________
Jmol-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jmol-developers