summaryrefslogtreecommitdiffstats
path: root/mono/Message.cs
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-06-22 20:46:17 +0000
committerHavoc Pennington <hp@redhat.com>2003-06-22 20:46:17 +0000
commit958805418359aca169cd363a4a3279f0fdab753c (patch)
treeef4d016dad313df8ad0c6f86cd715067a67c82a3 /mono/Message.cs
parent6843ad31769c088ca259020fd9ea8dfb3a51f68e (diff)
2003-06-22 Havoc Pennington <hp@pobox.com>
* mono/Message.cs: implement Message.Wrap() that ensures we only have a single C# wrapper per DBusMessage, assuming it works which it probably doesn't. * dbus/dbus-message.c (dbus_message_allocate_data_slot): new (dbus_message_free_data_slot): new (dbus_message_set_data): new (dbus_message_get_data): new
Diffstat (limited to 'mono/Message.cs')
-rw-r--r--mono/Message.cs86
1 files changed, 81 insertions, 5 deletions
diff --git a/mono/Message.cs b/mono/Message.cs
index 84bd12ec..0e41c9ec 100644
--- a/mono/Message.cs
+++ b/mono/Message.cs
@@ -2,12 +2,15 @@ namespace DBus {
using System;
using System.Runtime.InteropServices;
+ using System.Diagnostics;
public class Message {
public Message (string name,
string dest_service) {
+ // the assignment bumps the refcount
raw = dbus_message_new (name, dest_service);
+ dbus_message_unref (raw);
}
public string Name {
@@ -15,23 +18,80 @@ namespace DBus {
return dbus_message_get_name (raw);
}
}
-
- IntPtr raw;
+
+ public static Message Wrap (IntPtr ptr) {
+ IntPtr gch_ptr;
+
+ gch_ptr = dbus_message_get_data (ptr, wrapper_slot);
+ if (gch_ptr != (IntPtr) 0) {
+ return (DBus.Message) ((GCHandle)gch_ptr).Target;
+ } else {
+ return new Message (ptr);
+ }
+ }
+
+ // surely there's a convention for this pattern with the property
+ // and the real member
+ IntPtr raw_;
+ IntPtr raw {
+ get {
+ return raw_;
+ }
+ set {
+ if (value == raw_)
+ return;
+
+ if (raw_ != (IntPtr) 0) {
+ IntPtr gch_ptr;
+
+ gch_ptr = dbus_message_get_data (raw_,
+ wrapper_slot);
+ Debug.Assert (gch_ptr != (IntPtr) 0);
+
+ dbus_message_set_data (raw_, wrapper_slot,
+ (IntPtr) 0, (IntPtr) 0);
+
+ ((GCHandle) gch_ptr).Free ();
+
+ dbus_message_unref (raw_);
+ }
+
+ raw_ = value;
+
+ if (raw_ != (IntPtr) 0) {
+ GCHandle gch;
+
+ dbus_message_ref (raw_);
+
+ // We store a weak reference to the C# object on the C object
+ gch = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
+
+ dbus_message_set_data (raw_, wrapper_slot,
+ (IntPtr) gch, (IntPtr) 0);
+ }
+ }
+ }
~Message () {
- dbus_message_unref (raw);
+ raw = (IntPtr) 0; // free the native object
}
Message (IntPtr r) {
raw = r;
- dbus_message_ref (r);
}
// static constructor runs before any methods
static Message () {
+ Debug.Assert (wrapper_slot == -1);
+ if (!dbus_message_allocate_data_slot (ref wrapper_slot))
+ throw new OutOfMemoryException ();
+
+ Debug.Assert (wrapper_slot >= 0);
}
-
+
+ // slot used to store the C# object on the C object
+ static int wrapper_slot = -1;
const string libname = "libdbus-1.so.0";
[DllImport (libname, EntryPoint="dbus_message_new")]
@@ -46,5 +106,21 @@ namespace DBus {
[DllImport (libname, EntryPoint="dbus_message_get_name")]
private extern static string dbus_message_get_name (IntPtr ptr);
+
+ [DllImport (libname, EntryPoint="dbus_message_allocate_data_slot")]
+ private extern static bool dbus_message_allocate_data_slot (ref int slot);
+
+ [DllImport (libname, EntryPoint="dbus_message_free_data_slot")]
+ private extern static void dbus_message_free_data_slot (ref int slot);
+
+ [DllImport (libname, EntryPoint="dbus_message_set_data")]
+ private extern static bool dbus_message_set_data (IntPtr ptr,
+ int slot,
+ IntPtr data,
+ IntPtr free_data_func);
+
+ [DllImport (libname, EntryPoint="dbus_message_get_data")]
+ private extern static IntPtr dbus_message_get_data (IntPtr ptr,
+ int slot);
}
}