summaryrefslogtreecommitdiff
path: root/gstreamer-sharp/glib-sharp/DelegateWrapper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'gstreamer-sharp/glib-sharp/DelegateWrapper.cs')
-rw-r--r--gstreamer-sharp/glib-sharp/DelegateWrapper.cs111
1 files changed, 111 insertions, 0 deletions
diff --git a/gstreamer-sharp/glib-sharp/DelegateWrapper.cs b/gstreamer-sharp/glib-sharp/DelegateWrapper.cs
new file mode 100644
index 0000000..841d554
--- /dev/null
+++ b/gstreamer-sharp/glib-sharp/DelegateWrapper.cs
@@ -0,0 +1,111 @@
+// DelegateWrapper.cs - Delegate wrapper implementation
+//
+// Authors:
+// Rachel Hestilow <hestilow@ximian.com>
+// Gonzalo Panigua Javier <gonzalo@ximian.com>
+//
+// Copyright (c) 2002 Rachel Hestilow
+// Copyright (c) 2003 Ximian, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the Lesser GNU General
+// Public License as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GLib {
+
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class DelegateWrapper
+ {
+ // Keys in the hashtable are instances of classes derived from this one.
+ // Values are each instance's destroy notification delegate
+ static Hashtable instances = new Hashtable ();
+
+ // This list holds references to wrappers for static
+ // methods. These will never expire.
+ static ArrayList static_instances = new ArrayList ();
+
+ static int notify_count = 0;
+
+ // The object 'o' is the object that creates the instance of the DelegateWrapper
+ // derived class or null if created from a static method.
+ // Note that the instances will never be disposed if they are created in a static
+ // method.
+ [Obsolete ("Callback wrappers should be manually managed for persistence.")]
+ protected DelegateWrapper (object o)
+ {
+ if (o != null) {
+ // If o is a GObject, we can get
+ // destroy notification. Otherwise
+ // no additional references to
+ // the wrapper are kept.
+ // FIXME: This should work because
+ // currently only GObjects store
+ // callbacks over the long-term
+
+ if (o is GLib.Object) {
+ AddDestroyNotify ((GLib.Object) o);
+ }
+ } else {
+ // If o is null, we cannot ask for a destroy
+ // notification, so the wrapper never expires.
+
+ lock (typeof (DelegateWrapper)) {
+ static_instances.Add (this);
+ }
+ }
+ }
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ private delegate void DestroyNotify (IntPtr data);
+
+ [DllImport("libgobject-2.0-0.dll")]
+ private static extern void g_object_set_data_full (IntPtr obj, IntPtr name, IntPtr data, DestroyNotify destroy);
+
+ private void AddDestroyNotify (GLib.Object o) {
+ // This is a bit of an ugly hack. There is no
+ // way of getting a destroy notification
+ // explicitly, so we set some data and ask
+ // for notification when it is removed
+
+ IntPtr name = Marshaller.StringToPtrGStrdup (String.Format ("_GtkSharpDelegateWrapper_{0}", notify_count));
+ DestroyNotify destroy = new DestroyNotify (this.OnDestroy);
+
+ g_object_set_data_full (o.Handle, name, IntPtr.Zero, destroy);
+ Marshaller.Free (name);
+ lock (typeof (DelegateWrapper)) {
+ instances[this] = destroy;
+ notify_count++;
+ }
+ }
+
+ // This callback is invoked by GLib to indicate that the
+ // object that owned the native delegate wrapper no longer
+ // exists and the instance of the delegate itself is removed from the hash table.
+ private void OnDestroy (IntPtr data) {
+ try {
+ lock (typeof (DelegateWrapper)) {
+ if (instances.ContainsKey (this)) {
+ instances.Remove (this);
+ }
+ }
+ } catch (Exception e) {
+ ExceptionManager.RaiseUnhandledException (e, false);
+ }
+ }
+ }
+}
+