This fixes some remaining locking issue in AsyncImage. There was still a
small chance of tripping into NPEs here. This also fixes the
checkImage() issue which showed up in Mauve.

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

        * gnu/java/awt/peer/gtk/AsyncImage.java
        (Loader.run): Synchronize on the AsyncImage to avoid threading
        issues.
        (addObservers): Check for obs==null outside and synchronize on
        this inside to avoid locking issues.
        (checkImage): New helper method.
        (notifyObservers): Check that the correct lock is held and
        remove actual locking.
        * gnu/java/awt/peer/gtk/GtkToolkit.java
        (checkImage): Added special handling for AsyncImages.

/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.4
diff -u -1 -5 -r1.4 AsyncImage.java
--- gnu/java/awt/peer/gtk/AsyncImage.java	6 Dec 2006 21:53:23 -0000	1.4
+++ gnu/java/awt/peer/gtk/AsyncImage.java	6 Dec 2006 22:19:47 -0000
@@ -114,33 +114,36 @@
     }
 
     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.
+      synchronized (AsyncImage.this)
+        {
+          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;
 
   /**
    * The image observers.
    *
    * This is package private to avoid accessor methods.
    */
   HashSet observers;
 
@@ -200,71 +203,81 @@
     return source;
   }
 
   public int getWidth(ImageObserver observer)
   {
     addObserver(observer);
     int width = 0;
     Image r = realImage;
     if (r != null)
       width = r.getWidth(observer);
     return width;
   }
 
   void addObserver(ImageObserver obs)
   {
-    // 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 (obs != null)
       {
-        if (obs != null)
+        synchronized (this)
           {
-            synchronized (observs)
+            // 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)
               {
                 observs.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));
+              }
           }
       }
-    else if (obs != null)
-      {
-        // 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)
   {
+    assert Thread.holdsLock(this);
     // This field gets null when image loading is complete.
     HashSet observs = observers;
     if (observs != null)
       {
-        synchronized (observs)
+        Image r = realImage;
+        Iterator i = observs.iterator();
+        while (i.hasNext())
           {
-            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));
-              }
+            ImageObserver obs = (ImageObserver) i.next();
+            obs.imageUpdate(this, status, 0, 0, r.getWidth(null),
+                            r.getHeight(null));
           }
       }
   }
+
+  int checkImage(ImageObserver obs)
+  {
+    addObserver(obs);
+    int flags = 0;
+    if (realImage != null)
+      flags = ImageObserver.ALLBITS | ImageObserver.WIDTH
+              | ImageObserver.HEIGHT | ImageObserver.PROPERTIES;
+    return flags;
+  }
 }
Index: gnu/java/awt/peer/gtk/GtkToolkit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java,v
retrieving revision 1.97
diff -u -1 -5 -r1.97 GtkToolkit.java
--- gnu/java/awt/peer/gtk/GtkToolkit.java	5 Dec 2006 11:11:16 -0000	1.97
+++ gnu/java/awt/peer/gtk/GtkToolkit.java	6 Dec 2006 22:19:47 -0000
@@ -164,30 +164,33 @@
 
   public native void beep();
 
   private native void getScreenSizeDimensions(int[] xy);
   
   public int checkImage (Image image, int width, int height, 
 			 ImageObserver observer) 
   {
     int status = ImageObserver.ALLBITS 
       | ImageObserver.WIDTH 
       | ImageObserver.HEIGHT;
 
     if (image instanceof GtkImage)
 	return ((GtkImage) image).checkImage (observer);
 
+    if (image instanceof AsyncImage)
+      return ((AsyncImage) image).checkImage(observer);
+
     if (observer != null)
       observer.imageUpdate (image, status,
                             -1, -1,
                             image.getWidth (observer),
                             image.getHeight (observer));
     
     return status;
   }
 
   /** 
    * Helper to return either a Image -- the argument -- or a
    * GtkImage with the errorLoading flag set if the argument is null.
    */
   static Image imageOrError(Image b)
   {

Reply via email to