From 1c5b25f9a1efe7b6509627b5a8d290df53ff5b64 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 15 Mar 2003 20:49:37 +0000 Subject: [PATCH] 2003-03-11 Miguel de Icaza * gtk/Application.cs (CurrentEvent): Property implementing the suggestion from Paolo. * glib/Object.cs (Dispose): Destructor might be invoked in a thread, queue the object for destruction using the Gtk idle handler. We perform the real destruction of the object in the same thread as the Gtk+ main thread. svn path=/trunk/gtk-sharp/; revision=12551 --- ChangeLog | 12 +++++++ glib/Object.cs | 58 +++++++++++++++++++++++-------- gtk/Application.cs | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2eec771c5..33f828556 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-03-11 Miguel de Icaza + + * gtk/Application.cs (CurrentEvent): Property implementing the + suggestion from Paolo. + + * glib/Object.cs (Dispose): Destructor might be invoked in a + thread, queue the object for destruction using the Gtk idle + handler. We perform the real destruction of the object in the + same thread as the Gtk+ main thread. + 2003-03-14 Charles Iliya Krempeaux * sources/makefile : Added a "distclean" rule, so @@ -37,6 +47,8 @@ (InitCheck): new method, wraps gtk_init_check. + Removed inline docs from here. Put them on the documen + 2003-03-08 Miguel de Icaza * glib/Idle.cs: Add private constructor. diff --git a/glib/Object.cs b/glib/Object.cs index 9739aa702..5b9829e3f 100644 --- a/glib/Object.cs +++ b/glib/Object.cs @@ -4,7 +4,10 @@ // Mike Kestner // // (c) 2001 Bob Smith and Mike Kestner - +// +// TODO: +// Could remove `disposed' for a check if an object is on the dispose_queue_list. +// namespace GLib { using System; @@ -36,12 +39,40 @@ namespace GLib { bool disposed = false; Hashtable Data; static Hashtable Objects = new Hashtable(); + static Queue PendingDestroys = new Queue (); + static bool idle_queued; + // + // The destructor is invoked by a thread + // ~Object () { Dispose (); } + static bool PerformQueuedUnrefs () + { + Object [] objects; + + lock (PendingDestroys){ + objects = new Object [PendingDestroys.Count]; + PendingDestroys.CopyTo (objects, 0); + PendingDestroys.Clear (); + } + lock (typeof (Object)) + idle_queued = false; + + foreach (Object o in objects){ + if (o._obj == IntPtr.Zero) + continue; + + Objects.Remove (o._obj); + o.Unref (); + o._obj = IntPtr.Zero; + } + return false; + } + /// /// Dispose Method /// @@ -57,25 +88,22 @@ namespace GLib { if (disposed) return; - DisposeNative (); disposed = true; + lock (PendingDestroys){ + PendingDestroys.Enqueue (this); + lock (typeof (Object)){ + if (!idle_queued){ + Idle.Add (new IdleHandler (PerformQueuedUnrefs)); + idle_queued = true; + } + } + } + GC.SuppressFinalize (this); } [DllImport("libgobject-2.0-0.dll")] static extern void g_object_unref (IntPtr raw); - protected virtual void DisposeNative () - { - if (_obj == IntPtr.Zero) - return; - - Objects.Remove (Raw); - - GC.SuppressFinalize (this); - g_object_unref (_obj); - _obj = IntPtr.Zero; - } - [DllImport("libgobject-2.0-0.dll")] static extern void g_object_ref (IntPtr raw); @@ -104,6 +132,8 @@ namespace GLib { /// Decreases the reference count on the native object. /// This method is used by generated classes and structs, /// and should not be used in user code. + /// + /// This method should not be invoked by a thread. /// public virtual void Unref () { diff --git a/gtk/Application.cs b/gtk/Application.cs index 2470809ee..aa70725fd 100755 --- a/gtk/Application.cs +++ b/gtk/Application.cs @@ -8,6 +8,7 @@ namespace Gtk { using System; using System.Runtime.InteropServices; + using Gdk; public class Application { @@ -87,5 +88,90 @@ namespace Gtk { [DllImport("libgtk-win32-2.0-0.dll")] static extern IntPtr gtk_get_current_event (); + + public object CurrentEvent { + get { + IntPtr handle = gtk_get_current_event (); + Gdk.EventType type; + + type = (Gdk.EventType) Marshal.ReadInt32 (handle); + switch (type){ + case EventType.Delete: + case EventType.Destroy: + // Fixme: do not know what this maps to. + break; + + case EventType.Expose: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventExpose)); + + case EventType.MotionNotify: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventMotion)); + + case EventType.ButtonPress: + case EventType.TwoButtonPress: + case EventType.ThreeButtonPress: + case EventType.ButtonRelease: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventButton)); + + case EventType.KeyPress: + case EventType.KeyRelease: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventKey)); + + case EventType.EnterNotify: + case EventType.LeaveNotify: + // FIXME: Do not know what this maps to. + break; + + case EventType.FocusChange: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventFocus)); + + case EventType.Configure: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventConfigure)); + + case EventType.Map: + case EventType.Unmap: + // FIXME: Do not know what this maps to. + break; + + case EventType.PropertyNotify: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventProperty)); + + case EventType.SelectionClear: + case EventType.SelectionRequest: + case EventType.SelectionNotify: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventSelection)); + + case EventType.ProximityIn: + case EventType.ProximityOut: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventProximity)); + + case EventType.DragEnter: + case EventType.DragLeave: + case EventType.DragMotion: + case EventType.DragStatus: + case EventType.DropFinished: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventDND)); + + case EventType.ClientEvent: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventClient)); + + case EventType.VisibilityNotify: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventVisibility)); + + case EventType.NoExpose: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventNoExpose)); + + case EventType.Scroll: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventScroll)); + + case EventType.WindowState: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventWindowState)); + + case EventType.Setting: + return Marshal.PtrToStructure (handle, typeof (Gdk.EventSetting)); + } + return null; + } + } } }