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

Reply via email to