From 6843ad31769c088ca259020fd9ea8dfb3a51f68e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 22 Jun 2003 19:39:47 +0000 Subject: [PATCH] 2003-06-22 Havoc Pennington * dbus/dbus-dataslot.c (_dbus_data_slot_allocator_unref) (_dbus_data_slot_allocator_alloc): rework these to keep a reference count on each slot and automatically manage a global slot ID variable passed in by address * bus/bus.c: convert to new dataslot API * dbus/dbus-bus.c: convert to new dataslot API * dbus/dbus-connection.c: convert to new dataslot API * dbus/dbus-server.c: convert to new dataslot API * glib/dbus-gmain.c: ditto * bus/test.c: ditto * bus/connection.c: ditto --- ChangeLog | 21 ++++++++++ bus/bus.c | 51 +++++------------------ bus/connection.c | 42 ++----------------- bus/dispatch.c | 47 +++------------------- bus/test.c | 42 ++----------------- dbus/dbus-bus.c | 61 ++++------------------------ dbus/dbus-connection.c | 41 +++++++++++-------- dbus/dbus-connection.h | 8 ++-- dbus/dbus-dataslot.c | 100 ++++++++++++++++++++++++++++++++-------------- dbus/dbus-dataslot.h | 16 ++++++-- dbus/dbus-server.c | 29 ++++++++------ dbus/dbus-server.h | 4 +- glib/dbus-gmain.c | 24 +++++------ glib/test-thread-server.c | 5 ++- 14 files changed, 194 insertions(+), 297 deletions(-) diff --git a/ChangeLog b/ChangeLog index 377ceb4..b98f18c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2003-06-22 Havoc Pennington + + * dbus/dbus-dataslot.c (_dbus_data_slot_allocator_unref) + (_dbus_data_slot_allocator_alloc): rework these to keep a + reference count on each slot and automatically manage a global + slot ID variable passed in by address + + * bus/bus.c: convert to new dataslot API + + * dbus/dbus-bus.c: convert to new dataslot API + + * dbus/dbus-connection.c: convert to new dataslot API + + * dbus/dbus-server.c: convert to new dataslot API + + * glib/dbus-gmain.c: ditto + + * bus/test.c: ditto + + * bus/connection.c: ditto + 2003-06-22 Anders Carlsson * configure.in: Add AM_PROG_GCJ and move AM_PROG_LIBTOOL diff --git a/bus/bus.c b/bus/bus.c index e86243a..a553097 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -48,8 +48,7 @@ struct BusContext BusLimits limits; }; -static int server_data_slot = -1; -static int server_data_slot_refcount = 0; +static dbus_int32_t server_data_slot = -1; typedef struct { @@ -58,57 +57,25 @@ typedef struct #define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot)) -static dbus_bool_t -server_data_slot_ref (void) -{ - if (server_data_slot < 0) - { - server_data_slot = dbus_server_allocate_data_slot (); - - if (server_data_slot < 0) - return FALSE; - - _dbus_assert (server_data_slot_refcount == 0); - } - - server_data_slot_refcount += 1; - - return TRUE; -} - -static void -server_data_slot_unref (void) -{ - _dbus_assert (server_data_slot_refcount > 0); - - server_data_slot_refcount -= 1; - - if (server_data_slot_refcount == 0) - { - dbus_server_free_data_slot (server_data_slot); - server_data_slot = -1; - } -} - static BusContext* server_get_context (DBusServer *server) { BusContext *context; BusServerData *bd; - if (!server_data_slot_ref ()) + if (!dbus_server_allocate_data_slot (&server_data_slot)) return NULL; bd = BUS_SERVER_DATA (server); if (bd == NULL) { - server_data_slot_unref (); + dbus_server_free_data_slot (&server_data_slot); return NULL; } context = bd->context; - server_data_slot_unref (); + dbus_server_free_data_slot (&server_data_slot); return context; } @@ -303,7 +270,7 @@ bus_context_new (const DBusString *config_file, return NULL; } - if (!server_data_slot_ref ()) + if (!dbus_server_allocate_data_slot (&server_data_slot)) { BUS_SET_OOM (error); _dbus_string_free (&full_address); @@ -358,7 +325,7 @@ bus_context_new (const DBusString *config_file, /* we need another ref of the server data slot for the context * to own */ - if (!server_data_slot_ref ()) + if (!dbus_server_allocate_data_slot (&server_data_slot)) _dbus_assert_not_reached ("second ref of server data slot failed"); context->user_database = _dbus_user_database_new (); @@ -633,7 +600,7 @@ bus_context_new (const DBusString *config_file, bus_config_parser_unref (parser); _dbus_string_free (&full_address); dbus_free_string_array (auth_mechanisms); - server_data_slot_unref (); + dbus_server_free_data_slot (&server_data_slot); return context; @@ -647,7 +614,7 @@ bus_context_new (const DBusString *config_file, _dbus_string_free (&full_address); dbus_free_string_array (auth_mechanisms); - server_data_slot_unref (); + dbus_server_free_data_slot (&server_data_slot); return NULL; } @@ -769,7 +736,7 @@ bus_context_unref (BusContext *context) dbus_free (context); - server_data_slot_unref (); + dbus_server_free_data_slot (&server_data_slot); } } diff --git a/bus/connection.c b/bus/connection.c index 70a0eb1..5121658 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -43,8 +43,7 @@ struct BusConnections DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */ }; -static int connection_data_slot = -1; -static int connection_data_slot_refcount = 0; +static dbus_int32_t connection_data_slot = -1; typedef struct { @@ -67,39 +66,6 @@ static dbus_bool_t expire_incomplete_timeout (void *data); #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) -static dbus_bool_t -connection_data_slot_ref (void) -{ - if (connection_data_slot < 0) - { - connection_data_slot = dbus_connection_allocate_data_slot (); - - if (connection_data_slot < 0) - return FALSE; - - _dbus_assert (connection_data_slot_refcount == 0); - } - - connection_data_slot_refcount += 1; - - return TRUE; - -} - -static void -connection_data_slot_unref (void) -{ - _dbus_assert (connection_data_slot_refcount > 0); - - connection_data_slot_refcount -= 1; - - if (connection_data_slot_refcount == 0) - { - dbus_connection_free_data_slot (connection_data_slot); - connection_data_slot = -1; - } -} - static DBusLoop* connection_get_loop (DBusConnection *connection) { @@ -419,7 +385,7 @@ bus_connections_new (BusContext *context) { BusConnections *connections; - if (!connection_data_slot_ref ()) + if (!dbus_connection_allocate_data_slot (&connection_data_slot)) goto failed_0; connections = dbus_new0 (BusConnections, 1); @@ -456,7 +422,7 @@ bus_connections_new (BusContext *context) failed_2: dbus_free (connections); failed_1: - connection_data_slot_unref (); + dbus_connection_free_data_slot (&connection_data_slot); failed_0: return NULL; } @@ -515,7 +481,7 @@ bus_connections_unref (BusConnections *connections) dbus_free (connections); - connection_data_slot_unref (); + dbus_connection_free_data_slot (&connection_data_slot); } } diff --git a/bus/dispatch.c b/bus/dispatch.c index 8b2ba08..d43e812 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -32,8 +32,7 @@ #include #include -static int message_handler_slot = -1; -static int message_handler_slot_refcount; +static dbus_int32_t message_handler_slot = -1; typedef struct { @@ -309,48 +308,15 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } -static dbus_bool_t -message_handler_slot_ref (void) -{ - if (message_handler_slot < 0) - { - message_handler_slot = dbus_connection_allocate_data_slot (); - - if (message_handler_slot < 0) - return FALSE; - - _dbus_assert (message_handler_slot_refcount == 0); - } - - message_handler_slot_refcount += 1; - - return TRUE; -} - -static void -message_handler_slot_unref (void) -{ - _dbus_assert (message_handler_slot_refcount > 0); - - message_handler_slot_refcount -= 1; - - if (message_handler_slot_refcount == 0) - { - dbus_connection_free_data_slot (message_handler_slot); - message_handler_slot = -1; - } -} - static void free_message_handler (void *data) { DBusMessageHandler *handler = data; _dbus_assert (message_handler_slot >= 0); - _dbus_assert (message_handler_slot_refcount > 0); dbus_message_handler_unref (handler); - message_handler_slot_unref (); + dbus_connection_free_data_slot (&message_handler_slot); } dbus_bool_t @@ -358,26 +324,25 @@ bus_dispatch_add_connection (DBusConnection *connection) { DBusMessageHandler *handler; - if (!message_handler_slot_ref ()) + if (!dbus_connection_allocate_data_slot (&message_handler_slot)) return FALSE; handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL); if (handler == NULL) { - message_handler_slot_unref (); + dbus_connection_free_data_slot (&message_handler_slot); return FALSE; } if (!dbus_connection_add_filter (connection, handler)) { dbus_message_handler_unref (handler); - message_handler_slot_unref (); + dbus_connection_free_data_slot (&message_handler_slot); return FALSE; } _dbus_assert (message_handler_slot >= 0); - _dbus_assert (message_handler_slot_refcount > 0); if (!dbus_connection_set_data (connection, message_handler_slot, @@ -385,7 +350,7 @@ bus_dispatch_add_connection (DBusConnection *connection) free_message_handler)) { dbus_message_handler_unref (handler); - message_handler_slot_unref (); + dbus_connection_free_data_slot (&message_handler_slot); return FALSE; } diff --git a/bus/test.c b/bus/test.c index f8d4c5f..30cbcd0 100644 --- a/bus/test.c +++ b/bus/test.c @@ -123,41 +123,7 @@ client_disconnect_handler (DBusMessageHandler *handler, return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } -static int handler_slot = -1; -static int handler_slot_refcount = 0; - -static dbus_bool_t -handler_slot_ref (void) -{ - if (handler_slot < 0) - { - handler_slot = dbus_connection_allocate_data_slot (); - - if (handler_slot < 0) - return FALSE; - - _dbus_assert (handler_slot_refcount == 0); - } - - handler_slot_refcount += 1; - - return TRUE; - -} - -static void -handler_slot_unref (void) -{ - _dbus_assert (handler_slot_refcount > 0); - - handler_slot_refcount -= 1; - - if (handler_slot_refcount == 0) - { - dbus_connection_free_data_slot (handler_slot); - handler_slot = -1; - } -} +static dbus_int32_t handler_slot = -1; static void free_handler (void *data) @@ -165,7 +131,7 @@ free_handler (void *data) DBusMessageHandler *handler = data; dbus_message_handler_unref (handler); - handler_slot_unref (); + dbus_connection_free_data_slot (&handler_slot); } dbus_bool_t @@ -217,7 +183,7 @@ bus_setup_debug_client (DBusConnection *connection) if (!_dbus_list_append (&clients, connection)) goto out; - if (!handler_slot_ref ()) + if (!dbus_connection_allocate_data_slot (&handler_slot)) goto out; /* Set up handler to be destroyed */ @@ -225,7 +191,7 @@ bus_setup_debug_client (DBusConnection *connection) disconnect_handler, free_handler)) { - handler_slot_unref (); + dbus_connection_free_data_slot (&handler_slot); goto out; } diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index dee9b9f..6ab1ecc 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -56,12 +56,9 @@ typedef struct unsigned int is_well_known : 1; /**< Is one of the well-known connections in our global array */ } BusData; -/** The slot we have reserved to store BusData +/** The slot we have reserved to store BusData. */ -static int bus_data_slot = -1; -/** Number of connections using the slot - */ -static int bus_data_slot_refcount = 0; +static dbus_int32_t bus_data_slot = -1; /** Number of bus types */ #define N_BUS_TYPES 3 @@ -194,50 +191,6 @@ init_connections_unlocked (void) return initialized; } -static dbus_bool_t -data_slot_ref (void) -{ - _DBUS_LOCK (bus); - - if (bus_data_slot < 0) - { - bus_data_slot = dbus_connection_allocate_data_slot (); - - if (bus_data_slot < 0) - { - _DBUS_UNLOCK (bus); - return FALSE; - } - - _dbus_assert (bus_data_slot_refcount == 0); - } - - bus_data_slot_refcount += 1; - - _DBUS_UNLOCK (bus); - - return TRUE; -} - -static void -data_slot_unref (void) -{ - _DBUS_LOCK (bus); - - _dbus_assert (bus_data_slot_refcount > 0); - _dbus_assert (bus_data_slot >= 0); - - bus_data_slot_refcount -= 1; - - if (bus_data_slot_refcount == 0) - { - dbus_connection_free_data_slot (bus_data_slot); - bus_data_slot = -1; - } - - _DBUS_UNLOCK (bus); -} - static void bus_data_free (void *data) { @@ -262,7 +215,7 @@ bus_data_free (void *data) dbus_free (bd->base_service); dbus_free (bd); - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); } static BusData* @@ -270,7 +223,7 @@ ensure_bus_data (DBusConnection *connection) { BusData *bd; - if (!data_slot_ref ()) + if (!dbus_connection_allocate_data_slot (&bus_data_slot)) return NULL; bd = dbus_connection_get_data (connection, bus_data_slot); @@ -279,7 +232,7 @@ ensure_bus_data (DBusConnection *connection) bd = dbus_new0 (BusData, 1); if (bd == NULL) { - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); return NULL; } @@ -289,7 +242,7 @@ ensure_bus_data (DBusConnection *connection) bus_data_free)) { dbus_free (bd); - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); return NULL; } @@ -297,7 +250,7 @@ ensure_bus_data (DBusConnection *connection) } else { - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); } return bd; diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d877a0b..01b2a7b 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2933,34 +2933,41 @@ _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); * Allocates an integer ID to be used for storing application-specific * data on any DBusConnection. The allocated ID may then be used * with dbus_connection_set_data() and dbus_connection_get_data(). - * If allocation fails, -1 is returned. Again, the allocated - * slot is global, i.e. all DBusConnection objects will + * 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 DBusConnection objects will * have a slot with the given integer ID reserved. * - * @returns -1 on failure, otherwise the data slot ID + * @param slot_p address of a global variable storing the slot + * @returns #FALSE on failure (no memory) */ -int -dbus_connection_allocate_data_slot (void) +dbus_bool_t +dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - _DBUS_LOCK_NAME (connection_slots)); + _DBUS_LOCK_NAME (connection_slots), + slot_p); } /** * Deallocates a global ID for connection data slots. - * dbus_connection_get_data() and dbus_connection_set_data() - * may no longer be used with this slot. - * Existing data stored on existing DBusConnection objects - * will be freed when the connection is finalized, - * but may not be retrieved (and may only be replaced - * if someone else reallocates the slot). + * dbus_connection_get_data() and dbus_connection_set_data() may no + * longer be used with this slot. Existing data stored on existing + * DBusConnection objects will be freed when the connection 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 the slot to deallocate + * @param slot_p address storing the slot to deallocate */ void -dbus_connection_free_data_slot (int slot) +dbus_connection_free_data_slot (dbus_int32_t *slot_p) { - _dbus_data_slot_allocator_free (&slot_allocator, slot); + _dbus_return_if_fail (*slot_p >= 0); + + _dbus_data_slot_allocator_free (&slot_allocator, slot_p); } /** @@ -2978,7 +2985,7 @@ dbus_connection_free_data_slot (int slot) */ dbus_bool_t dbus_connection_set_data (DBusConnection *connection, - int slot, + dbus_int32_t slot, void *data, DBusFreeFunction free_data_func) { @@ -3018,7 +3025,7 @@ dbus_connection_set_data (DBusConnection *connection, */ void* dbus_connection_get_data (DBusConnection *connection, - int slot) + dbus_int32_t slot) { void *res; diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index c2206cd..9f4dd7a 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -172,14 +172,14 @@ void dbus_connection_unregister_handler (DBusConnection *connection, int n_messages); -int dbus_connection_allocate_data_slot (void); -void dbus_connection_free_data_slot (int slot); +dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p); +void dbus_connection_free_data_slot (dbus_int32_t *slot_p); dbus_bool_t dbus_connection_set_data (DBusConnection *connection, - int slot, + dbus_int32_t slot, void *data, DBusFreeFunction free_data_func); void* dbus_connection_get_data (DBusConnection *connection, - int slot); + dbus_int32_t slot); void dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe); diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c index def864e..defe934 100644 --- a/dbus/dbus-dataslot.c +++ b/dbus/dbus-dataslot.c @@ -53,24 +53,25 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) /** * Allocates an integer ID to be used for storing data - * in a #DBusDataSlotList. - * - * @todo all over the code we have foo_slot and foo_slot_refcount, - * would be better to add an interface for that to - * DBusDataSlotAllocator so it isn't cut-and-pasted everywhere. + * in a #DBusDataSlotList. If the value at *slot_id_p is + * not -1, this function just increments the refcount for + * the existing slot ID. If the value is -1, a new slot ID + * is allocated and stored at *slot_id_p. * * @param allocator the allocator * @param mutex the lock for this allocator - * @returns the integer ID, or -1 on failure + * @param slot_id_p address to fill with the slot ID + * @returns #TRUE on success */ -int +dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusMutex *mutex) + DBusMutex *mutex, + dbus_int32_t *slot_id_p) { - int slot; + dbus_int32_t slot; if (!dbus_mutex_lock (mutex)) - return -1; + return FALSE; if (allocator->n_allocated_slots == 0) { @@ -79,15 +80,30 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, } else _dbus_assert (allocator->lock == mutex); + + if (*slot_id_p >= 0) + { + slot = *slot_id_p; + + _dbus_assert (slot < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + + allocator->allocated_slots[slot].refcount += 1; + + goto out; + } + + _dbus_assert (*slot_id_p < 0); if (allocator->n_used_slots < allocator->n_allocated_slots) { slot = 0; while (slot < allocator->n_allocated_slots) { - if (allocator->allocated_slots[slot] < 0) + if (allocator->allocated_slots[slot].slot_id < 0) { - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; allocator->n_used_slots += 1; break; } @@ -98,11 +114,11 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, } else { - int *tmp; + DBusAllocatedSlot *tmp; slot = -1; tmp = dbus_realloc (allocator->allocated_slots, - sizeof (int) * (allocator->n_allocated_slots + 1)); + sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1)); if (tmp == NULL) goto out; @@ -110,18 +126,24 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, slot = allocator->n_allocated_slots; allocator->n_allocated_slots += 1; allocator->n_used_slots += 1; - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; } _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - + _dbus_assert (*slot_id_p < 0); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + _dbus_assert (allocator->allocated_slots[slot].refcount == 1); + + *slot_id_p = slot; + _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n", slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); out: dbus_mutex_unlock (allocator->lock); - return slot; + return slot >= 0; } /** @@ -130,24 +152,37 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, * existing #DBusDataList objects with this ID will be freed when the * data list is finalized, but may not be retrieved (and may only be * replaced if someone else reallocates the slot). + * The slot value is reset to -1 if this is the last unref. * * @param allocator the allocator - * @param slot the slot to deallocate + * @param slot_id_p address where we store the slot */ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, - int slot) + dbus_int32_t *slot_id_p) { dbus_mutex_lock (allocator->lock); - _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (*slot_id_p < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p); + _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0); + + allocator->allocated_slots[*slot_id_p].refcount -= 1; + + if (allocator->allocated_slots[*slot_id_p].refcount > 0) + { + dbus_mutex_unlock (allocator->lock); + return; + } + + /* refcount is 0, free the slot */ + _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n", + *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots); + + allocator->allocated_slots[*slot_id_p].slot_id = -1; + *slot_id_p = -1; - allocator->allocated_slots[slot] = -1; allocator->n_used_slots -= 1; - - _dbus_verbose ("Freed slot %d on allocator %p total %d allocated %d used\n", - slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); if (allocator->n_used_slots == 0) { @@ -211,7 +246,7 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, if (!dbus_mutex_lock (allocator->lock)) return FALSE; _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); dbus_mutex_unlock (allocator->lock); #endif @@ -270,7 +305,7 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, return FALSE; _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); dbus_mutex_unlock (allocator->lock); #endif @@ -355,7 +390,11 @@ _dbus_data_slot_test (void) * allocation, but it simplifies things to rely on it * here. */ - if (_dbus_data_slot_allocator_alloc (&allocator, mutex) != i) + dbus_int32_t tmp = -1; + + _dbus_data_slot_allocator_alloc (&allocator, mutex, &tmp); + + if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); ++i; @@ -411,7 +450,10 @@ _dbus_data_slot_test (void) i = 0; while (i < N_SLOTS) { - _dbus_data_slot_allocator_free (&allocator, i); + dbus_int32_t tmp = i; + + _dbus_data_slot_allocator_free (&allocator, &tmp); + _dbus_assert (tmp == -1); ++i; } diff --git a/dbus/dbus-dataslot.h b/dbus/dbus-dataslot.h index d435732..6f591eb 100644 --- a/dbus/dbus-dataslot.h +++ b/dbus/dbus-dataslot.h @@ -39,9 +39,16 @@ struct DBusDataSlot DBusFreeFunction free_data_func; /**< Free the application data */ }; +typedef struct DBusAllocatedSlot DBusAllocatedSlot; +struct DBusAllocatedSlot +{ + dbus_int32_t slot_id; /**< ID of this slot */ + int refcount; /**< Number of uses of the slot */ +}; + struct DBusDataSlotAllocator { - int *allocated_slots; /**< Allocated slots */ + DBusAllocatedSlot *allocated_slots; /**< Allocated slots */ int n_allocated_slots; /**< number of slots malloc'd */ int n_used_slots; /**< number of slots used */ DBusMutex *lock; /**< thread lock */ @@ -54,10 +61,11 @@ struct DBusDataSlotList }; dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator); -int _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusMutex *mutex); +dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, + DBusMutex *mutex, + int *slot_id_p); void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, - int slot_id); + int *slot_id_p); void _dbus_data_slot_list_init (DBusDataSlotList *list); dbus_bool_t _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, DBusDataSlotList *list, diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 4007d7a..1c9d53f 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -666,17 +666,22 @@ _DBUS_DEFINE_GLOBAL_LOCK (server_slots); * Allocates an integer ID to be used for storing application-specific * data on any DBusServer. The allocated ID may then be used * with dbus_server_set_data() and dbus_server_get_data(). - * If allocation fails, -1 is returned. Again, the allocated - * slot is global, i.e. all DBusServer objects will - * have a slot with the given integer ID reserved. - * - * @returns -1 on failure, otherwise the data slot ID + * The slot must be initialized with -1. If a nonnegative + * slot is passed in, the refcount is incremented on that + * slot, rather than creating a new slot. + * + * The allocated slot is global, i.e. all DBusServer objects will have + * a slot with the given integer ID reserved. + * + * @param slot_p address of global variable storing the slot ID + * @returns #FALSE on no memory */ -int -dbus_server_allocate_data_slot (void) +dbus_bool_t +dbus_server_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - _DBUS_LOCK_NAME (server_slots)); + _DBUS_LOCK_NAME (server_slots), + slot_p); } /** @@ -688,14 +693,14 @@ dbus_server_allocate_data_slot (void) * but may not be retrieved (and may only be replaced * if someone else reallocates the slot). * - * @param slot the slot to deallocate + * @param slot_p address of the slot to deallocate */ void -dbus_server_free_data_slot (int slot) +dbus_server_free_data_slot (dbus_int32_t *slot_p) { - _dbus_return_if_fail (slot >= 0); + _dbus_return_if_fail (*slot_p >= 0); - _dbus_data_slot_allocator_free (&slot_allocator, slot); + _dbus_data_slot_allocator_free (&slot_allocator, slot_p); } /** diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 5527f1e..c2a0ca0 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -65,8 +65,8 @@ dbus_bool_t dbus_server_set_timeout_functions (DBusServer * dbus_bool_t dbus_server_set_auth_mechanisms (DBusServer *server, const char **mechanisms); -int dbus_server_allocate_data_slot (void); -void dbus_server_free_data_slot (int slot); +dbus_bool_t dbus_server_allocate_data_slot (dbus_int32_t *slot_p); +void dbus_server_free_data_slot (dbus_int32_t *slot_p); dbus_bool_t dbus_server_set_data (DBusServer *server, int slot, void *data, diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index c120a6c..9b14049 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -60,10 +60,8 @@ struct DBusGSource void *connection_or_server; /**< DBusConnection or DBusServer */ }; -static GStaticMutex connection_slot_lock = G_STATIC_MUTEX_INIT; -static int connection_slot = -1; -static GStaticMutex server_slot_lock = G_STATIC_MUTEX_INIT; -static int server_slot = -1; +static dbus_int32_t connection_slot = -1; +static dbus_int32_t server_slot = -1; static gboolean gsource_connection_prepare (GSource *source, gint *timeout); @@ -428,11 +426,10 @@ dbus_connection_setup_with_g_main (DBusConnection *connection, g_source_attach (source, context); - g_static_mutex_lock (&connection_slot_lock); - if (connection_slot == -1 ) - connection_slot = dbus_connection_allocate_data_slot (); - g_static_mutex_unlock (&connection_slot_lock); - + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_connection_allocate_data_slot (&connection_slot); if (connection_slot < 0) goto nomem; @@ -476,11 +473,10 @@ dbus_server_setup_with_g_main (DBusServer *server, g_source_attach (source, context); - g_static_mutex_lock (&server_slot_lock); - if (server_slot == -1 ) - server_slot = dbus_server_allocate_data_slot (); - g_static_mutex_unlock (&server_slot_lock); - + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_server_allocate_data_slot (&server_slot); if (server_slot < 0) goto nomem; diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c index a92febf..00044a7 100644 --- a/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -27,7 +27,7 @@ thread_test_data_free (ThreadTestData *data) static DBusMessageHandler *disconnect_handler; static DBusMessageHandler *filter_handler; -static int handler_slot; +static dbus_int32_t handler_slot = -1; static DBusHandlerResult handle_test_message (DBusMessageHandler *handler, @@ -222,7 +222,8 @@ main (int argc, char *argv[]) return 1; } - handler_slot = dbus_connection_allocate_data_slot (); + if (!dbus_connection_allocate_data_slot (&handler_slot)) + g_error ("no memory for data slot"); filter_handler = dbus_message_handler_new (handle_filter, NULL, NULL); -- 2.7.4