java-gobject-introspection r126 - in trunk: src/org/gnome/gir/compiler src/org/gnome/gir/gobject src/org/gnome/gir/repository stub-examples



Author: walters
Date: Sun Nov 16 23:58:56 2008
New Revision: 126
URL: http://svn.gnome.org/viewvc/java-gobject-introspection?rev=126&view=rev

Log:
Massive refactoring of memmgt

Strip out a lot of stuff from NativeObject that we really don't need since
we aren't trying to handle non-GObjects in any serious way right now.

GObject now just subclasses NativeObject.  RefCountedObject is a temporary
hack.

Modified:
   trunk/src/org/gnome/gir/compiler/CodeFactory.java
   trunk/src/org/gnome/gir/gobject/GInitiallyUnowned.java
   trunk/src/org/gnome/gir/gobject/GMainContext.java
   trunk/src/org/gnome/gir/gobject/GObject.java
   trunk/src/org/gnome/gir/gobject/GObjectAPI.java
   trunk/src/org/gnome/gir/gobject/GSource.java
   trunk/src/org/gnome/gir/gobject/GTypeMapper.java
   trunk/src/org/gnome/gir/gobject/Handle.java
   trunk/src/org/gnome/gir/gobject/NativeObject.java
   trunk/src/org/gnome/gir/gobject/RefCountedObject.java
   trunk/src/org/gnome/gir/repository/BaseInfo.java
   trunk/src/org/gnome/gir/repository/Repository.java
   trunk/stub-examples/Test.java

Modified: trunk/src/org/gnome/gir/compiler/CodeFactory.java
==============================================================================
--- trunk/src/org/gnome/gir/compiler/CodeFactory.java	(original)
+++ trunk/src/org/gnome/gir/compiler/CodeFactory.java	Sun Nov 16 23:58:56 2008
@@ -1280,7 +1280,7 @@
 					/* These are objects for which we do *not* own a reference.  */
 					mv.visitLdcInsn(ctx.returnType);
 					mv.visitInsn(ICONST_0);
-					mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeObject.class), "objectFor", 
+					mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeObject.Internals.class), "objectFor", 
 							Type.getMethodDescriptor(getType(NativeObject.class), new Type[] { getType(Pointer.class), getType(Class.class), Type.BOOLEAN_TYPE }));
 					mv.visitTypeInsn(CHECKCAST, ctx.returnType.getInternalName());					
 				} else if (returnTypeTag.equals(TypeTag.UTF8)) {

Modified: trunk/src/org/gnome/gir/gobject/GInitiallyUnowned.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GInitiallyUnowned.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GInitiallyUnowned.java	Sun Nov 16 23:58:56 2008
@@ -2,18 +2,15 @@
 
 
 public abstract class GInitiallyUnowned extends GObject {
-
+	/*
+	 * Note - memory management for this class is handled inside GObject, we
+	 * check whether an object is floating there.
+	 */
 	public GInitiallyUnowned(Initializer init) {
 		super(init);
 	}
-	
-	@Override
-	protected void ref() {
-		GObjectAPI.gobj.g_object_ref_sink(this);
-	}
 
 	protected GInitiallyUnowned(GType gtype, Object[] args) {
 		super(gtype, args);
 	}
-
 }

Modified: trunk/src/org/gnome/gir/gobject/GMainContext.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GMainContext.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GMainContext.java	Sun Nov 16 23:58:56 2008
@@ -63,18 +63,13 @@
         return glib.g_source_attach(source, this);
     }
     public static GMainContext getDefaultContext() {
-        return new GMainContext(initializer(glib.g_main_context_default(), false, false));
+        return new GMainContext(initializer(glib.g_main_context_default(), false));
     }
     
     protected void ref() {
-        glib.g_main_context_ref(handle());
+        glib.g_main_context_ref(getNativeAddress());
     }
     protected void unref() {
-        glib.g_main_context_unref(handle());
-    }
-
-    @Override
-    protected void disposeNativeHandle(Pointer ptr) {
-        glib.g_main_context_unref(ptr);
+        glib.g_main_context_unref(getNativeAddress());
     }
 }

Modified: trunk/src/org/gnome/gir/gobject/GObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GObject.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GObject.java	Sun Nov 16 23:58:56 2008
@@ -51,7 +51,6 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.gnome.gir.gobject.GObjectAPI.GObjectStruct;
 import org.gnome.gir.gobject.GObjectAPI.GParamSpec;
 import org.gnome.gir.gobject.GObjectAPI.GToggleNotify;
 import org.gnome.gir.gobject.GObjectAPI.GWeakNotify;
@@ -65,32 +64,11 @@
  * This is an abstract class providing some GObject-like facilities in a common 
  * base class.  Not intended for direct use.
  */
-public abstract class GObject extends RefCountedObject {
+public abstract class GObject extends NativeObject {
     private static final Map<GObject, Boolean> strongReferences = new ConcurrentHashMap<GObject, Boolean>();
 
     private final IntPtr objectID = new IntPtr(System.identityHashCode(this));
     
-    private static final boolean debugMemory;
-    
-    static {
-    	debugMemory = System.getProperty("jgir.debugMemory") != null;
-    }
-    
-    private static final void debugMemory(GObject obj, String fmt, Object... args) {
-    	if (debugMemory) {
-    		Object[] newArgs = new Object[args.length+2];
-    		System.arraycopy(args, 0, newArgs, 1, args.length);
-    		newArgs[0] = obj;
-    		if (obj != null) {
-    			GObjectStruct objStruct = new GObjectAPI.GObjectStruct(obj);    		
-    			newArgs[newArgs.length-1] = objStruct.ref_count;
-    		} else {
-    			newArgs[newArgs.length-1] = "<null>";
-    		}
-    		System.err.println(String.format(fmt, newArgs));
-    	}
-    }
-    
     /* Hold a strong Java reference between this proxy object and any signal
      * handlers installed.  Often this would be done anyways, but if you're
      * just calling System.out.println in a callback, it would otherwise
@@ -117,45 +95,46 @@
      * return values of unmanaged code.
      * @param init
      */
-    public GObject(Initializer init) { 
-        super(init.ownsRef ? initializer(init.ptr, false, init.ownsHandle) : init);
-        if (init.ownsHandle) {
-            strongReferences.put(this, Boolean.TRUE);
-            
-            /* Floating refs are just a convenience for C; we always want only strong
-             * nonfloating refs for objects which have a JVM peer.
-             */
-            boolean wasFloating = GObjectAPI.gobj.g_object_is_floating(this);
-            if (wasFloating) {
-            	debugMemory(this, "SINK AND TOGGLE %s %s");
-            	GObjectAPI.gobj.g_object_ref_sink(this);
-            } else {
-            	debugMemory(this, "TOGGLE %s %s");            	
-            }
-            
-            /* The toggle reference is our primary means of memory management between
-             * this Proxy object and the GObject.
-             */
-            GObjectAPI.gobj.g_object_add_toggle_ref(init.ptr, toggle, objectID);
-            
-            /* The weak notify is just a convenient hook into object destruction so we
-             * can clear out our signal handlers hash.
-             */
-            GObjectAPI.gobj.g_object_weak_ref(this, weakNotify, null);
+    public GObject(Initializer init) {
+        super(init);
+        
+        strongReferences.put(this, Boolean.TRUE);
             
-            /*
-			 * Normally we have a strong reference given to us by constructors,
-			 * GValue property gets, etc. So here we unref, leaving the toggle
-			 * reference we just added.
-			 * 
-			 * An example case where we don't own a ref are C convenience
-			 * getters - need to ensure those are annotated with (transfer
-			 * none).
-			 */ 
-            if (init.ownsRef) {
-                unref();
-            }            
-        }
+        /*
+		 * Floating refs are just a convenience for C; we always want only
+		 * strong nonfloating refs for objects which have a JVM peer.
+		 */
+		boolean wasFloating = GObjectAPI.gobj.g_object_is_floating(this);
+		if (wasFloating) {
+			NativeObject.Internals.debugMemory(this, "SINK AND TOGGLE %s %s");
+			GObjectAPI.gobj.g_object_ref_sink(this);
+		} else {
+			NativeObject.Internals.debugMemory(this, "TOGGLE %s %s");
+		}
+
+		/*
+		 * The toggle reference is our primary means of memory management
+		 * between this Proxy object and the GObject.
+		 */
+		GObjectAPI.gobj.g_object_add_toggle_ref(init.ptr, toggle, objectID);
+
+		/*
+		 * The weak notify is just a convenient hook into object destruction so
+		 * we can clear out our signal handlers hash.
+		 */
+		GObjectAPI.gobj.g_object_weak_ref(this, weakNotify, null);
+
+		/*
+		 * Normally we have a strong reference given to us by constructors,
+		 * GValue property gets, etc. So here we unref, leaving the toggle
+		 * reference we just added.
+		 * 
+		 * An example case where we don't own a ref are C convenience getters -
+		 * need to ensure those are annotated with (transfer none).
+		 */
+		if (init.ownsRef) {
+			GObjectAPI.gobj.g_object_unref(this);
+		}
     }
     
     private static Initializer getInitializer(GType gtype, Object[] args) {
@@ -208,8 +187,8 @@
      * Sets the value of a <tt>GObject</tt> property.
      *
      * @param property The property to set.
-     * @param data The value for the property.  This must be of the type expected
-     * by gstreamer.
+     * @param data The value for the property.  This must be an instance of
+     * a class which maps to the corresponding GType.
      */
     public void set(String property, Object data) {
         GParamSpec propertySpec = findProperty(property);
@@ -241,38 +220,11 @@
         return propValue.unboxAndUnset();
     }
     
-    protected void disposeNativeHandle(Pointer ptr) {
-        GObjectAPI.gobj.g_object_remove_toggle_ref(ptr, toggle, objectID);
-    }
-    @Override
-    protected void ref() {
-    	debugMemory(this, "REF %s %s");    	
-    	GObjectAPI.gobj.g_object_ref(this);
-    }
-
-    @Override
-    protected void unref() {
-    	debugMemory(this, "UNREF %s %s");    	
-    	GObjectAPI.gobj.g_object_unref(this);
-    }
-    
     @Override
-    protected void invalidate() {
-        try {
-        	debugMemory(this, "INVALIDATE %s %s");        	
-            // Need to increase the ref count before removing the toggle ref, so 
-            // ensure the native object is not destroyed.
-            if (ownsHandle.get()) {
-            	debugMemory(this, "REMOVING TOGGLE %s %s");             	
-                ref();
-
-                // Disconnect the callback.
-                GObjectAPI.gobj.g_object_remove_toggle_ref(handle(), toggle, objectID);
-            }
-            strongReferences.remove(this);
-        } finally { 
-            super.invalidate();
-        }
+    protected void finalize() throws Throwable {  	
+        NativeObject.Internals.debugMemory(this, "REMOVING TOGGLE %s %s");
+        /* Take away the toggle reference */
+        GObjectAPI.gobj.g_object_remove_toggle_ref(getNativeAddress(), toggle, objectID);
     }
  
     public synchronized long connect(String signal, Callback closure) {
@@ -292,6 +244,7 @@
     }
     
     public synchronized long connectNotify(final String propName, final Callback callback) {
+    	/* FIXME - need to hold this trampoline's lifecycle to the signal connection */
     	NotifyCallback trampoline = new NotifyCallback() {
 			@Override
 			public void onNotify(GObject object, GParamSpec param, Pointer data) {
@@ -323,7 +276,7 @@
     }
 
     private GObjectAPI.GParamSpec findProperty(String propertyName) {
-        return GObjectAPI.gobj.g_object_class_find_property(handle().getPointer(0), propertyName);
+        return GObjectAPI.gobj.g_object_class_find_property(getNativeAddress().getPointer(0), propertyName);
     }
     /*
      * Hooks to/from native disposal
@@ -337,10 +290,11 @@
              * it a strong ref, so the java GObject for the underlying C object can
              * be retained for later retrieval
              */
-            GObject o = (GObject) NativeObject.instanceFor(ptr);
+            GObject o = (GObject) Internals.instanceFor(ptr);
             if (o == null) {
                 return;
             }
+            NativeObject.Internals.debugMemory(o, "TOGGLE %s %d %s", is_last_ref);	            
             if (is_last_ref) {
                 strongReferences.remove(o);
             } else {
@@ -352,8 +306,8 @@
     private static final GWeakNotify weakNotify = new GWeakNotify() {
 		@Override
 		public void callback(Pointer data, Pointer obj) {
-			GObject o = (GObject) NativeObject.instanceFor(obj);
-            debugMemory(o, "WEAK %s %s obj=%s", o, obj);			
+			GObject o = (GObject) Internals.instanceFor(obj);
+            NativeObject.Internals.debugMemory(o, "WEAK %s %s obj=%s", o, obj);			
 			// Clear out the signal handler references
 			if (o == null)
 				return;

Modified: trunk/src/org/gnome/gir/gobject/GObjectAPI.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GObjectAPI.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GObjectAPI.java	Sun Nov 16 23:58:56 2008
@@ -146,7 +146,7 @@
         public volatile Pointer qdata;
         public GObjectStruct() {}
         public GObjectStruct(GObject obj) {
-            useMemory(obj.handle());
+            useMemory(obj.getNativeAddress());
             read();
         }
     }

Modified: trunk/src/org/gnome/gir/gobject/GSource.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GSource.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GSource.java	Sun Nov 16 23:58:56 2008
@@ -63,7 +63,7 @@
     public void setCallback(final Callable<Boolean> call) {
         this.callback = new GSourceFunc() {
             public boolean callback(Pointer data) {
-                if (GlibAPI.glib.g_source_is_destroyed(handle())) {
+                if (GlibAPI.glib.g_source_is_destroyed(getNativeAddress())) {
                     return false;
                 }
                 try {
@@ -78,15 +78,9 @@
     private GSourceFunc callback;
     
     protected void ref() {
-        GlibAPI.glib.g_source_ref(handle());
+        GlibAPI.glib.g_source_ref(getNativeAddress());
     }
     protected void unref() {
-        GlibAPI.glib.g_source_unref(handle());
-    }
-
-    @Override
-    protected void disposeNativeHandle(Pointer ptr) {
-        GlibAPI.glib.g_source_destroy(ptr);
-        GlibAPI.glib.g_source_unref(ptr);
+        GlibAPI.glib.g_source_unref(getNativeAddress());
     }
 }

Modified: trunk/src/org/gnome/gir/gobject/GTypeMapper.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/GTypeMapper.java	(original)
+++ trunk/src/org/gnome/gir/gobject/GTypeMapper.java	Sun Nov 16 23:58:56 2008
@@ -101,7 +101,7 @@
             if (arg == null) {
                 return null;
             }
-            Pointer ptr = ((NativeObject) arg).handle();
+            Pointer ptr = ((NativeObject) arg).getNativeAddress();
             return ptr;
         }
  
@@ -111,10 +111,10 @@
                 return null;
             }
             if (context instanceof FunctionResultContext) {
-            	return NativeObject.objectFor((Pointer) result, context.getTargetType(), true, true);
+            	return NativeObject.Internals.objectFor((Pointer) result, context.getTargetType(), true);
             }            
             if (context instanceof CallbackParameterContext || context instanceof StructureReadContext) {
-                return NativeObject.objectFor((Pointer) result, context.getTargetType(), false, true);
+                return NativeObject.Internals.objectFor((Pointer) result, context.getTargetType(), false);
             }
             if (context instanceof MethodResultContext) {
             	throw new RuntimeException("Got illegal MethodResultContext in GTypeMapper");

Modified: trunk/src/org/gnome/gir/gobject/Handle.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/Handle.java	(original)
+++ trunk/src/org/gnome/gir/gobject/Handle.java	Sun Nov 16 23:58:56 2008
@@ -51,21 +51,19 @@
     // Use this to propagate low level pointer arguments up the constructor chain
     protected static class Initializer {
         public final Pointer ptr;
-        public final boolean ownsRef, ownsHandle;
+        public final boolean ownsRef;
         
         public Initializer(Pointer ptr) {
-        	this(ptr, true, true);
+        	this(ptr, true);
         }
-        public Initializer(Pointer ptr, boolean ownsRef, boolean ownsHandle) {
+        public Initializer(Pointer ptr, boolean ownsRef) {
         	if (ptr == null)
         		throw new RuntimeException("Invalid NULL pointer for initializer");
             this.ptr = ptr;
             this.ownsRef = ownsRef;
-            this.ownsHandle = ownsHandle;
         }
     }  
 
     public Handle() {
     }
-    abstract protected void invalidate();
 }

Modified: trunk/src/org/gnome/gir/gobject/NativeObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/NativeObject.java	(original)
+++ trunk/src/org/gnome/gir/gobject/NativeObject.java	Sun Nov 16 23:58:56 2008
@@ -53,6 +53,7 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.gnome.gir.gobject.GObjectAPI.GObjectStruct;
 import org.gnome.gir.repository.BaseInfo;
 
 import com.sun.jna.Pointer;
@@ -61,13 +62,10 @@
  *
  */
 public abstract class NativeObject extends Handle {
-    private final AtomicBoolean disposed = new AtomicBoolean(false);
-    private final AtomicBoolean valid = new AtomicBoolean(true);
     private final Pointer handle;
-    protected final AtomicBoolean ownsHandle = new AtomicBoolean(false);
     private final NativeRef nativeRef;
     
-    private static final ConcurrentMap<Pointer, NativeRef> instanceMap = new ConcurrentHashMap<Pointer, NativeRef>();    
+    private static final ConcurrentMap<Pointer, NativeRef> instanceMap = new ConcurrentHashMap<Pointer, NativeRef>();     
     
     static class NativeRef extends WeakReference<NativeObject> {
         public NativeRef(NativeObject obj) {
@@ -80,13 +78,13 @@
      * they own the native object.  Special cases can use the other constructor.
      */
     protected static Initializer initializer(Pointer ptr) {
-        return initializer(ptr, false, true);
+        return initializer(ptr, false);
     }
-    protected static Initializer initializer(Pointer ptr, boolean needRef, boolean ownsHandle) {
+    protected static Initializer initializer(Pointer ptr, boolean needRef) {
         if (ptr == null) {
             throw new IllegalArgumentException("Invalid native pointer");
         }
-        return new Initializer(ptr, needRef, ownsHandle);
+        return new Initializer(ptr, needRef);
     }
     /** Creates a new instance of NativeObject */
     protected NativeObject(final Initializer init) {
@@ -95,7 +93,6 @@
         }
         nativeRef = new NativeRef(this);
         this.handle = init.ptr;
-        this.ownsHandle.set(init.ownsHandle);
         
         //
         // Only store this object in the map if we can tell when it has been disposed 
@@ -108,149 +105,143 @@
         }
         
     }
-    
-    abstract protected void disposeNativeHandle(Pointer ptr);
-    
-    public void dispose() {
-        if (!disposed.getAndSet(true)) {
-            instanceMap.remove(handle, nativeRef);
-            if (ownsHandle.get()) {
-                disposeNativeHandle(handle);
-            }
-            valid.set(false);
-        }
-    }
-    
-    protected void invalidate() {
-        instanceMap.remove(handle(), nativeRef);
-        disposed.set(true);
-        ownsHandle.set(false);
-        valid.set(false);
-    }
-    
+
     @Override
     protected void finalize() throws Throwable {
-        try {
-            dispose();
-        } finally {
-            super.finalize();
-        }
+        instanceMap.remove(handle, nativeRef);
+        super.finalize();
     }
+    
     protected Object nativeValue() {
-        return handle();
-    }
-    protected Pointer handle() {
-        if (!valid.get()) {
-            throw new IllegalStateException("Native object has been disposed");
-        }
-        return handle;
+        return getNativeAddress();
     }
+
     public Pointer getNativeAddress() {
         return handle;
     }
-    protected boolean isDisposed() {
-        return disposed.get();
-    }
-    protected static NativeObject instanceFor(Pointer ptr) {
-        WeakReference<NativeObject> ref = instanceMap.get(ptr);
-        
-        //
-        // If the reference was there, but the object it pointed to had been collected, remove it from the map
-        //
-        if (ref != null && ref.get() == null) {
-            instanceMap.remove(ptr);
-        }
-        return ref != null ? ref.get() : null;
-    }
-    public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef) {
-        return objectFor(ptr, cls, ownsRef, true);
-    }
-    
-    private static Class<?> getStubClassFor(Class<?> proxyClass) {
-    	Class<?>[] declared = proxyClass.getDeclaredClasses();
-    	for (Class<?> c: declared) {
-    		if (c.getName().endsWith("$AnonStub"))
-    			return c;
-    	}
-    	throw new RuntimeException("Couldn't find Stub for interface: " + proxyClass);
-    }
     
-	public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef, boolean ownsHandle) {
-		return objectFor(ptr, cls, ownsRef, ownsHandle, true);
-	}
-    
-    @SuppressWarnings("unchecked")
-	public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef, boolean ownsHandle, boolean peekGType) {
-        // Ignore null pointers
-        if (ptr == null) {
-            return null;
-        }
-        NativeObject obj = null;
-        if (BaseInfo.class.isAssignableFrom(cls))
-        	obj = BaseInfo.newInstanceFor(ptr);
-        else if (GObject.class.isAssignableFrom(cls) || GObject.GObjectProxy.class.isAssignableFrom(cls))
-        	obj = NativeObject.instanceFor(ptr);
-        if (obj != null && cls.isInstance(obj)) {
-            if (ownsRef) {
-                ((RefCountedObject) obj).unref(); // Lose the extra ref that we expect functions to add by default
-            }
-            return cls.cast(obj);
-        }
-       
+    public static class Internals {
 
-        /* Special-case GObject.GObjectProxy here - these are interface values
-         * for which we don't know of a current concrete class.
-         */
-        if (cls.isInterface() && GObject.GObjectProxy.class.isAssignableFrom(cls)) {
-    		cls = (Class<T>) getStubClassFor(cls);        	
+        public static final boolean debugMemory;
+        
+        static {
+        	debugMemory = System.getProperty("jgir.debugMemory") != null;
         }
-        /* For GObject, read the g_class field to find
-         * the most exact class match
-         */        	
-        else if (peekGType && GObject.class.isAssignableFrom(cls)) {
-        	cls = classFor(ptr, cls);
-        	/* If it's abstract, pull out the stub */
-        	if ((cls.getModifiers() & Modifier.ABSTRACT) != 0)
-        		cls = (Class<T>) getStubClassFor(cls);
+        
+        public static final void debugMemory(GObject obj, String fmt, Object... args) {
+        	if (debugMemory) {
+        		Object[] newArgs = new Object[args.length+2];
+        		System.arraycopy(args, 0, newArgs, 1, args.length);
+        		newArgs[0] = obj;
+        		if (obj != null) {
+        			GObjectStruct objStruct = new GObjectAPI.GObjectStruct(obj);    		
+        			newArgs[newArgs.length-1] = objStruct.ref_count;
+        		} else {
+        			newArgs[newArgs.length-1] = "<null>";
+        		}
+        		System.err.println(String.format(fmt, newArgs));
+        	}
         }        
-        /* Ok, let's try to find an Initializer constructor
-         */
-        try {
-            Constructor<T> constructor = cls.getDeclaredConstructor(Initializer.class);
-            constructor.setAccessible(true);
-            T retVal = constructor.newInstance(initializer(ptr, ownsRef, ownsHandle));
-            //retVal.initNativeHandle(ptr, refAdjust > 0, ownsHandle);
-            return retVal;
-        } catch (SecurityException ex) {
-            throw new RuntimeException(ex);
-        } catch (IllegalAccessException ex) {
-            throw new RuntimeException(ex);
-        } catch (InstantiationException ex) {
-            throw new RuntimeException(ex);
-        } catch (NoSuchMethodException ex) {
-            throw new RuntimeException(ex);
-        } catch (InvocationTargetException ex) {
-            throw new RuntimeException(ex);
-        }
-
+    	
+		protected static NativeObject instanceFor(Pointer ptr) {
+		    WeakReference<NativeObject> ref = NativeObject.instanceMap.get(ptr);
+		    
+		    //
+		    // If the reference was there, but the object it pointed to had been collected, remove it from the map
+		    //
+		    if (ref != null && ref.get() == null) {
+		        NativeObject.instanceMap.remove(ptr);
+		    }
+		    return ref != null ? ref.get() : null;
+		}
+
+		private static Class<?> getStubClassFor(Class<?> proxyClass) {
+			Class<?>[] declared = proxyClass.getDeclaredClasses();
+			for (Class<?> c: declared) {
+				if (c.getName().endsWith("$AnonStub"))
+					return c;
+			}
+			throw new RuntimeException("Couldn't find Stub for interface: " + proxyClass);
+		}		
+
+	    public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef) {
+			return objectFor(ptr, cls, ownsRef, true);
+		}
+	    
+	    @SuppressWarnings("unchecked")
+		public static <T extends NativeObject> T objectFor(Pointer ptr, Class<T> cls, boolean ownsRef, boolean peekGType) {
+	        // Ignore null pointers
+	        if (ptr == null) {
+	            return null;
+	        }
+	        NativeObject obj = null;
+	        if (BaseInfo.class.isAssignableFrom(cls))
+	        	obj = BaseInfo.newInstanceFor(ptr);
+	        else if (GObject.class.isAssignableFrom(cls) || GObject.GObjectProxy.class.isAssignableFrom(cls))
+	        	obj = Internals.instanceFor(ptr);
+	        if (obj != null && cls.isInstance(obj)) {
+	            if (ownsRef) {
+	                ((RefCountedObject) obj).unref(); // Lose the extra ref that we expect functions to add by default
+	            }
+	            return cls.cast(obj);
+	        }
+	       
+
+	        /* Special-case GObject.GObjectProxy here - these are interface values
+	         * for which we don't know of a current concrete class.
+	         */
+	        if (cls.isInterface() && GObject.GObjectProxy.class.isAssignableFrom(cls)) {
+	    		cls = (Class<T>) Internals.getStubClassFor(cls);        	
+	        }
+	        /* For GObject, read the g_class field to find
+	         * the most exact class match
+	         */        	
+	        else if (peekGType && GObject.class.isAssignableFrom(cls)) {
+	        	cls = classFor(ptr, cls);
+	        	/* If it's abstract, pull out the stub */
+	        	if ((cls.getModifiers() & Modifier.ABSTRACT) != 0)
+	        		cls = (Class<T>) Internals.getStubClassFor(cls);
+	        }        
+	        /* Ok, let's try to find an Initializer constructor
+	         */
+	        try {
+	            Constructor<T> constructor = cls.getDeclaredConstructor(Initializer.class);
+	            constructor.setAccessible(true);
+	            T retVal = constructor.newInstance(initializer(ptr, ownsRef));
+	            //retVal.initNativeHandle(ptr, refAdjust > 0, ownsHandle);
+	            return retVal;
+	        } catch (SecurityException ex) {
+	            throw new RuntimeException(ex);
+	        } catch (IllegalAccessException ex) {
+	            throw new RuntimeException(ex);
+	        } catch (InstantiationException ex) {
+	            throw new RuntimeException(ex);
+	        } catch (NoSuchMethodException ex) {
+	            throw new RuntimeException(ex);
+	        } catch (InvocationTargetException ex) {
+	            throw new RuntimeException(ex);
+	        }
+
+	    }
+	    
+	    @SuppressWarnings("unchecked")
+		protected static Class<?> lookupProxyChain(GType gtype) {
+	    	Class<?> ret = null;
+	    	while (ret == null && !gtype.equals(GType.OBJECT)) {
+	    		ret = GType.lookupProxyClass(gtype);
+	    		gtype = gtype.getParent();
+	    	}
+	    	return ret;
+	    }
+	    
+	    @SuppressWarnings("unchecked")
+		protected static <T extends NativeObject> Class<T> classFor(Pointer ptr, Class<T> defaultClass) {
+	    	GType gtype = GType.objectPeekType(ptr);
+	    	Class<?> cls = lookupProxyChain(gtype);
+	    	return (cls != null && defaultClass.isAssignableFrom(cls)) ? (Class<T>) cls : defaultClass; 
+	    }
     }
     
-    @SuppressWarnings("unchecked")
-	protected static Class<?> lookupProxyChain(GType gtype) {
-    	Class<?> ret = null;
-    	while (ret == null && !gtype.equals(GType.OBJECT)) {
-    		ret = GType.lookupProxyClass(gtype);
-    		gtype = gtype.getParent();
-    	}
-    	return ret;
-    }
-    
-    @SuppressWarnings("unchecked")
-	protected static <T extends NativeObject> Class<T> classFor(Pointer ptr, Class<T> defaultClass) {
-    	GType gtype = GType.objectPeekType(ptr);
-    	Class<?> cls = lookupProxyChain(gtype);
-    	return (cls != null && defaultClass.isAssignableFrom(cls)) ? (Class<T>) cls : defaultClass; 
-    }    
 
     @Override
     public boolean equals(Object o) {
@@ -264,13 +255,6 @@
     
     @Override
     public String toString() {
-        return getClass().getSimpleName() + "(" + handle() + ")";
-    }
-    
-    //
-    // No longer want to garbage collect this object
-    //
-    public void disown() {
-        ownsHandle.set(false);
+        return getClass().getSimpleName() + "(" + getNativeAddress() + ")";
     }
 }

Modified: trunk/src/org/gnome/gir/gobject/RefCountedObject.java
==============================================================================
--- trunk/src/org/gnome/gir/gobject/RefCountedObject.java	(original)
+++ trunk/src/org/gnome/gir/gobject/RefCountedObject.java	Sun Nov 16 23:58:56 2008
@@ -53,11 +53,17 @@
     /** Creates a new instance of RefCountedObject */
     protected RefCountedObject(Initializer init) {
         super(init);
-        if (init.ownsHandle && init.ownsRef) {
+        if (!init.ownsRef) {
             ref();
         }
     }
     // overridden in subclasses
     abstract protected void ref();
     abstract protected void unref();
+    
+    @Override
+    protected void finalize() throws Throwable {
+    	unref();
+    	super.finalize();
+    }
 }

Modified: trunk/src/org/gnome/gir/repository/BaseInfo.java
==============================================================================
--- trunk/src/org/gnome/gir/repository/BaseInfo.java	(original)
+++ trunk/src/org/gnome/gir/repository/BaseInfo.java	Sun Nov 16 23:58:56 2008
@@ -18,7 +18,7 @@
 			String name = GIntrospectionAPI.gi.g_base_info_get_name(ptr);
 			throw new UnresolvedException(namespace, name);
 		}
-		Initializer init = new Initializer(ptr, false, false);		
+		Initializer init = new Initializer(ptr, true);		
 		if (itype == InfoType.ENUM.ordinal())
 			return new EnumInfo(init);
 		if (itype == InfoType.FLAGS.ordinal())
@@ -43,7 +43,7 @@
 			return new PropertyInfo(init);
 		if (itype == InfoType.CONSTANT.ordinal())
 			return new ConstantInfo(init);				
-		return new BaseInfo(new Initializer(ptr));
+		return new BaseInfo(init);
 	}
 
 	@Override
@@ -58,18 +58,13 @@
 	
 	public String getName() {
 		if (cachedName == null)
-			cachedName = Repository.getNativeLibrary().g_base_info_get_name(this.handle());
+			cachedName = Repository.getNativeLibrary().g_base_info_get_name(getNativeAddress());
 		return cachedName;
 	}
 
-	@Override
-	protected void disposeNativeHandle(Pointer ptr) {
-		unref();
-	}
-
 	public String getNamespace() {
 		if (cachedNamespace == null)
-			cachedNamespace = GIntrospectionAPI.gi.g_base_info_get_namespace(this.handle());
+			cachedNamespace = GIntrospectionAPI.gi.g_base_info_get_namespace(getNativeAddress());
 		return cachedNamespace;
 	}
 	

Modified: trunk/src/org/gnome/gir/repository/Repository.java
==============================================================================
--- trunk/src/org/gnome/gir/repository/Repository.java	(original)
+++ trunk/src/org/gnome/gir/repository/Repository.java	Sun Nov 16 23:58:56 2008
@@ -87,8 +87,8 @@
 	
 	public static synchronized Repository getDefault() {
 		GObjectGlobals.init();
-		return (Repository) NativeObject.objectFor(getNativeLibrary().g_irepository_get_default(),
-									  Repository.class, false, true, false);
+		return (Repository) NativeObject.Internals.objectFor(getNativeLibrary().g_irepository_get_default(),
+									  Repository.class, false, false);
 	}
 	
 	public void unloadAll() {

Modified: trunk/stub-examples/Test.java
==============================================================================
--- trunk/stub-examples/Test.java	(original)
+++ trunk/stub-examples/Test.java	Sun Nov 16 23:58:56 2008
@@ -80,7 +80,7 @@
 		if (error.getValue() != null) {
 			throw new GErrorException(new GErrorStruct(error.getValue()));
 		}
-		return (Test) NativeObject.objectFor(result, Test.class, false);
+		return (Test) NativeObject.Internals.objectFor(result, Test.class, false);
 	}	
 	
 	public static Test newWithFoo(String blah) {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]