mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 09:58:07 +02:00
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
This commit is contained in:
parent
6843ad3176
commit
9588054183
6 changed files with 222 additions and 6 deletions
11
ChangeLog
11
ChangeLog
|
|
@ -1,3 +1,14 @@
|
|||
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
|
||||
|
||||
2003-06-22 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-dataslot.c (_dbus_data_slot_allocator_unref)
|
||||
|
|
|
|||
|
|
@ -229,12 +229,13 @@ extern int _dbus_current_generation;
|
|||
_DBUS_DECLARE_GLOBAL_LOCK (list);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (message_handler);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (bus);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (system_users);
|
||||
#define _DBUS_N_GLOBAL_LOCKS (8)
|
||||
#define _DBUS_N_GLOBAL_LOCKS (9)
|
||||
|
||||
dbus_bool_t _dbus_threads_init_debug (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbus-memory.h"
|
||||
#include "dbus-list.h"
|
||||
#include "dbus-message-builder.h"
|
||||
#include "dbus-dataslot.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
|
|
@ -107,6 +108,8 @@ struct DBusMessage
|
|||
dbus_uint32_t changed_stamp; /**< Incremented when iterators are invalidated. */
|
||||
|
||||
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
|
||||
|
||||
DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -913,6 +916,8 @@ dbus_message_new_empty_header (void)
|
|||
message->byte_order = DBUS_COMPILER_BYTE_ORDER;
|
||||
message->client_serial = 0;
|
||||
message->reply_serial = 0;
|
||||
|
||||
_dbus_data_slot_list_init (&message->slot_list);
|
||||
|
||||
i = 0;
|
||||
while (i < FIELD_LAST)
|
||||
|
|
@ -1184,6 +1189,9 @@ dbus_message_unref (DBusMessage *message)
|
|||
|
||||
if (old_refcount == 1)
|
||||
{
|
||||
/* This calls application callbacks! */
|
||||
_dbus_data_slot_list_free (&message->slot_list);
|
||||
|
||||
_dbus_list_foreach (&message->size_counters,
|
||||
free_size_counter, message);
|
||||
_dbus_list_clear (&message->size_counters);
|
||||
|
|
@ -4609,6 +4617,114 @@ _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
|
|||
return loader->max_message_size;
|
||||
}
|
||||
|
||||
static DBusDataSlotAllocator slot_allocator;
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (message_slots);
|
||||
|
||||
/**
|
||||
* Allocates an integer ID to be used for storing application-specific
|
||||
* data on any DBusMessage. The allocated ID may then be used
|
||||
* with dbus_message_set_data() and dbus_message_get_data().
|
||||
* The passed-in slot must be initialized to -1, and is filled in
|
||||
* with the slot ID. If the passed-in slot is not -1, it's assumed
|
||||
* to be already allocated, and its refcount is incremented.
|
||||
*
|
||||
* The allocated slot is global, i.e. all DBusMessage objects will
|
||||
* have a slot with the given integer ID reserved.
|
||||
*
|
||||
* @param slot_p address of a global variable storing the slot
|
||||
* @returns #FALSE on failure (no memory)
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
|
||||
{
|
||||
return _dbus_data_slot_allocator_alloc (&slot_allocator,
|
||||
_DBUS_LOCK_NAME (message_slots),
|
||||
slot_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocates a global ID for message data slots.
|
||||
* dbus_message_get_data() and dbus_message_set_data() may no
|
||||
* longer be used with this slot. Existing data stored on existing
|
||||
* DBusMessage objects will be freed when the message is
|
||||
* finalized, but may not be retrieved (and may only be replaced if
|
||||
* someone else reallocates the slot). When the refcount on the
|
||||
* passed-in slot reaches 0, it is set to -1.
|
||||
*
|
||||
* @param slot_p address storing the slot to deallocate
|
||||
*/
|
||||
void
|
||||
dbus_message_free_data_slot (dbus_int32_t *slot_p)
|
||||
{
|
||||
_dbus_return_if_fail (*slot_p >= 0);
|
||||
|
||||
_dbus_data_slot_allocator_free (&slot_allocator, slot_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a pointer on a DBusMessage, along
|
||||
* with an optional function to be used for freeing
|
||||
* the data when the data is set again, or when
|
||||
* the message is finalized. The slot number
|
||||
* must have been allocated with dbus_message_allocate_data_slot().
|
||||
*
|
||||
* @param message the message
|
||||
* @param slot the slot number
|
||||
* @param data the data to store
|
||||
* @param free_data_func finalizer function for the data
|
||||
* @returns #TRUE if there was enough memory to store the data
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_message_set_data (DBusMessage *message,
|
||||
dbus_int32_t slot,
|
||||
void *data,
|
||||
DBusFreeFunction free_data_func)
|
||||
{
|
||||
DBusFreeFunction old_free_func;
|
||||
void *old_data;
|
||||
dbus_bool_t retval;
|
||||
|
||||
_dbus_return_val_if_fail (message != NULL, FALSE);
|
||||
_dbus_return_val_if_fail (slot >= 0, FALSE);
|
||||
|
||||
retval = _dbus_data_slot_list_set (&slot_allocator,
|
||||
&message->slot_list,
|
||||
slot, data, free_data_func,
|
||||
&old_free_func, &old_data);
|
||||
|
||||
if (retval)
|
||||
{
|
||||
/* Do the actual free outside the message lock */
|
||||
if (old_free_func)
|
||||
(* old_free_func) (old_data);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves data previously set with dbus_message_set_data().
|
||||
* The slot must still be allocated (must not have been freed).
|
||||
*
|
||||
* @param message the message
|
||||
* @param slot the slot to get data from
|
||||
* @returns the data, or #NULL if not found
|
||||
*/
|
||||
void*
|
||||
dbus_message_get_data (DBusMessage *message,
|
||||
dbus_int32_t slot)
|
||||
{
|
||||
void *res;
|
||||
|
||||
_dbus_return_val_if_fail (message != NULL, NULL);
|
||||
|
||||
res = _dbus_data_slot_list_get (&slot_allocator,
|
||||
&message->slot_list,
|
||||
slot);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#include "dbus-test.h"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <dbus/dbus-macros.h>
|
||||
#include <dbus/dbus-types.h>
|
||||
#include <dbus/dbus-arch-deps.h>
|
||||
#include <dbus/dbus-memory.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
DBUS_BEGIN_DECLS;
|
||||
|
|
@ -231,6 +232,16 @@ dbus_bool_t dbus_message_iter_append_string_array (DBusMessageIter *iter,
|
|||
dbus_bool_t dbus_set_error_from_message (DBusError *error,
|
||||
DBusMessage *message);
|
||||
|
||||
|
||||
dbus_bool_t dbus_message_allocate_data_slot (dbus_int32_t *slot_p);
|
||||
void dbus_message_free_data_slot (dbus_int32_t *slot_p);
|
||||
dbus_bool_t dbus_message_set_data (DBusMessage *message,
|
||||
dbus_int32_t slot,
|
||||
void *data,
|
||||
DBusFreeFunction free_data_func);
|
||||
void* dbus_message_get_data (DBusMessage *message,
|
||||
dbus_int32_t slot);
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_MESSAGE_H */
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ init_global_locks (void)
|
|||
LOCK_ADDR (list),
|
||||
LOCK_ADDR (connection_slots),
|
||||
LOCK_ADDR (server_slots),
|
||||
LOCK_ADDR (message_slots),
|
||||
LOCK_ADDR (atomic),
|
||||
LOCK_ADDR (message_handler),
|
||||
LOCK_ADDR (bus),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue