summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-message.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-message.c')
-rw-r--r--dbus/dbus-message.c116
1 files changed, 116 insertions, 0 deletions
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 <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"