Hi,

A couple of drawing operations on CairoGraphics2D are implemented by
calling other drawing primitives. This means that a draw() might call
fill() later on for example. Since ComponentGraphics needs to acquire
the gdk lock before actually doing any drawing (through its super class
CairoGraphics2D) we would sometimes get a deadlock since the gdk lock
isn't reentrant. This patch makes the ComponentGraphics lock reentrant
by using a ThreadLocal that counts the number of locks and unlocks on a
particular Thread and only actually takes the gdk lock or releases it
when the count drops to zero.

2006-06-12  Mark Wielaard  <[EMAIL PROTECTED]>

        * gnu/java/awt/peer/gtk/ComponentGraphics.java (hasLock):
        New static field.
        (ONE): Likewise.
        (lock): New method.
        (unlock): Likewise.
        (draw): Use lock() and unlock().
        (fill): Likewise.
        (drawRenderedImage): Likewise.
        (drawImage): Likewise.
        (drawGlyphVector): Likewise.

I was a bit afraid this would impact drawing a lot, but I personally
don't notice any slowdown when using things. Since it solve some real
deadlocks for me I am checking this in.

Cheers,

Mark
Index: gnu/java/awt/peer/gtk/ComponentGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java,v
retrieving revision 1.13
diff -u -r1.13 ComponentGraphics.java
--- gnu/java/awt/peer/gtk/ComponentGraphics.java	11 Jun 2006 11:21:52 -0000	1.13
+++ gnu/java/awt/peer/gtk/ComponentGraphics.java	12 Jun 2006 12:15:34 -0000
@@ -67,6 +67,35 @@
   private GtkComponentPeer component;
   protected long cairo_t;
 
+  private static ThreadLocal hasLock = new ThreadLocal();
+  private static Integer ONE = Integer.valueOf(1);
+
+  private void lock()
+  {
+    Integer i = (Integer) hasLock.get();
+    if (i == null)
+      {
+	start_gdk_drawing();
+	hasLock.set(ONE);
+      }
+    else
+      hasLock.set(Integer.valueOf(i.intValue() + 1));
+  }
+
+  private void unlock()
+  {
+    Integer i = (Integer) hasLock.get();
+    if (i == null)
+      throw new IllegalStateException();
+    if (i == ONE)
+      {
+	hasLock.set(null);
+	end_gdk_drawing();
+      }
+    else
+      hasLock.set(Integer.valueOf(i.intValue() - 1));
+  }
+
   ComponentGraphics()
   {
   }
@@ -180,40 +209,40 @@
    */
   public void draw(Shape s)
   {
-    start_gdk_drawing();
+    lock();
     try
       {
 	super.draw(s);
       }
     finally
       {
-	end_gdk_drawing();
+	unlock();
       }
   }
 
   public void fill(Shape s)
   {
-    start_gdk_drawing();
+    lock();
     try
       {
 	super.fill(s);
       }
     finally
       {
-	end_gdk_drawing();
+	unlock();
       }
   }
 
   public void drawRenderedImage(RenderedImage image, AffineTransform xform)
   {
-    start_gdk_drawing();
+    lock();
     try
       {
 	super.drawRenderedImage(image, xform);
       }
     finally
       {
-	end_gdk_drawing();
+	unlock();
       }
   }
 
@@ -221,28 +250,28 @@
 			      Color bgcolor, ImageObserver obs)
   {
     boolean rv;
-    start_gdk_drawing();
+    lock();
     try
       {
 	rv = super.drawImage(img, xform, bgcolor, obs);
       }
     finally
       {
-	end_gdk_drawing();
+	unlock();
       }
     return rv;
   }
 
   public void drawGlyphVector(GlyphVector gv, float x, float y)
   {
-    start_gdk_drawing();
+    lock();
     try
       {
 	super.drawGlyphVector(gv, x, y);
       }
     finally
       {
-	end_gdk_drawing();
+	unlock();
       }
   }
   

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to