From 958805418359aca169cd363a4a3279f0fdab753c Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 22 Jun 2003 20:46:17 +0000 Subject: 2003-06-22 Havoc Pennington * 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 --- dbus/dbus-internals.h | 3 +- dbus/dbus-message.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-message.h | 11 +++++ dbus/dbus-threads.c | 1 + 4 files changed, 130 insertions(+), 1 deletion(-) (limited to 'dbus') diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index 6a0ae746..d84017d7 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -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); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 4d80425b..85d6ce9e 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -29,6 +29,7 @@ #include "dbus-memory.h" #include "dbus-list.h" #include "dbus-message-builder.h" +#include "dbus-dataslot.h" #include /** @@ -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" diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 177f5a91..9f07565c 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -30,6 +30,7 @@ #include #include #include +#include #include 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 */ diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c index 76b2f194..5f953d82 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -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), -- cgit