This discards all observers after the image loading is finished. They
are not needed anymore and new observers get pinged directly.

2006-12-05  Roman Kennke  <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/AsyncImage.java
        (Loader.run): Nullify observers after loading.
        (observers): Made package private.
        (addObserver): Check for null observers field. Create local
        variable for thread safety.
        (getHeight): Use addObserver() for checking state of field
        and notifying observer when necessary.
        (getWidth): Use addObserver() for checking state of field
        and notifying observer when necessary.
        (getProperty): Use addObserver() for checking state of field
        and notifying observer when necessary.
        (notifyObservers): Check for null observers field. Create local
        variable for thread safety.

/Roman

Index: gnu/java/awt/peer/gtk/AsyncImage.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/AsyncImage.java,v
retrieving revision 1.2
diff -u -1 -5 -r1.2 AsyncImage.java
--- gnu/java/awt/peer/gtk/AsyncImage.java	5 Dec 2006 21:38:33 -0000	1.2
+++ gnu/java/awt/peer/gtk/AsyncImage.java	5 Dec 2006 22:23:26 -0000
@@ -116,154 +116,155 @@
     public void run()
     {
       Image image;
       try
         {
           GtkImage gtkImage = new GtkImage(url);
           image = CairoSurface.getBufferedImage(gtkImage);
         }
       catch (IllegalArgumentException iae)
         {
           image = null;
         }
       realImage = GtkToolkit.imageOrError(image);
       notifyObservers(ImageObserver.ALLBITS | ImageObserver.HEIGHT
                       | ImageObserver.WIDTH | ImageObserver.PROPERTIES);
+      observers = null; // Not needed anymore.
     }
   }
 
   /**
    * The real image. This is null as long as the image is not complete.
    */
   Image realImage;
 
-  private HashSet observers;
+  /**
+   * The image observers.
+   *
+   * This is package private to avoid accessor methods.
+   */
+  HashSet observers;
 
   /**
    * Creates a new AsyncImage that loads from the specified URL.
    */
   AsyncImage(URL url)
   {
     observers = new HashSet();
     Loader l = new Loader(url);
     Thread t = new Thread(l);
     t.start();
   }
 
   public void flush()
   {
     // Nothing to do here.
   }
 
   public Graphics getGraphics()
   {
     Image r = realImage;
     Graphics g = null;
     if (r != null)
       g = r.getGraphics(); // Should we return some dummy graphics instead?
     return g;
   }
 
   public int getHeight(ImageObserver observer)
   {
-    if (observer != null)
-      {
-        synchronized (observers)
-          {
-            observers.add(observer);
-          }
-      }
+    addObserver(observer);
     int height = 0;
     Image r = realImage;
     if (r != null)
       height = r.getHeight(observer);
     return height;
   }
 
   public Object getProperty(String name, ImageObserver observer)
   {
-    if (observer != null)
-      {
-        synchronized (observers)
-          {
-            observers.add(observer);
-          }
-      }
+    addObserver(observer);
     Image r = realImage;
     Object prop = null;
     if (r != null)
       prop = r.getProperty(name, observer);
     return prop;
   }
 
   public ImageProducer getSource()
   {
     Image r = realImage;
     ImageProducer source;
     if (r == null)
       source = new NullImageSource();
     else
       source = r.getSource();
     return source;
   }
 
   public int getWidth(ImageObserver observer)
   {
-    if (observer != null)
-      {
-        synchronized (observers)
-          {
-            observers.add(observer);
-          }
-      }
+    addObserver(observer);
     int width = 0;
     Image r = realImage;
     if (r != null)
       width = r.getWidth(observer);
     return width;
   }
 
   void addObserver(ImageObserver obs)
   {
-    if (obs != null)
+    // This field gets null when image loading is complete and we don't
+    // need to store any more observers.
+    HashSet observs = observers;
+    if (observs != null)
       {
-        if (realImage != null && ! observers.contains(obs))
+        if (obs != null)
           {
-            obs.imageUpdate(this, ImageObserver.WIDTH | ImageObserver.HEIGHT
-                            |ImageObserver.ALLBITS | ImageObserver.PROPERTIES,
-                            0, 0, realImage.getWidth(null),
-                            realImage.getHeight(null));
+            synchronized (observs)
+              {
+                observs.add(obs);
+              }
           }
-        synchronized (observers)
-        {
-          observers.add(obs);
-        }
+      }
+    else
+      {
+        // When the image is complete, notify the observer. Dunno if that's
+        // really needed, but to be sure.
+        obs.imageUpdate(this, ImageObserver.WIDTH | ImageObserver.HEIGHT
+                        |ImageObserver.ALLBITS | ImageObserver.PROPERTIES,
+                        0, 0, realImage.getWidth(null),
+                        realImage.getHeight(null));
       }
   }
 
   static Image realImage(Image img, ImageObserver obs)
   {
     if (img instanceof AsyncImage)
       {
         ((AsyncImage) img).addObserver(obs);
         Image r = ((AsyncImage) img).realImage;
         if (r != null)
           img = r;
       }
     return img;
   }
 
   void notifyObservers(int status)
   {
-    synchronized (observers)
+    // This field gets null when image loading is complete.
+    HashSet observs = observers;
+    if (observs != null)
       {
-        Image r = realImage;
-        Iterator i = observers.iterator();
-        while (i.hasNext())
+        synchronized (observs)
           {
-            ImageObserver obs = (ImageObserver) i.next();
-            obs.imageUpdate(this, status, 0, 0, r.getWidth(null),
-                            r.getHeight(null));
+            Image r = realImage;
+            Iterator i = observs.iterator();
+            while (i.hasNext())
+              {
+                ImageObserver obs = (ImageObserver) i.next();
+                obs.imageUpdate(this, status, 0, 0, r.getWidth(null),
+                                r.getHeight(null));
+              }
           }
       }
   }
 }

Reply via email to