summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-06-22 19:39:47 +0000
committerHavoc Pennington <hp@redhat.com>2003-06-22 19:39:47 +0000
commit6843ad31769c088ca259020fd9ea8dfb3a51f68e (patch)
tree208e287bc200298da5514f4d32704f3e8ef42423
parent8a71cf33ef8f35669dbdb39ef2f12c5a3dfebf33 (diff)
2003-06-22 Havoc Pennington <hp@pobox.com>
* 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
-rw-r--r--ChangeLog21
-rw-r--r--bus/bus.c51
-rw-r--r--bus/connection.c42
-rw-r--r--bus/dispatch.c47
-rw-r--r--bus/test.c42
-rw-r--r--dbus/dbus-bus.c61
-rw-r--r--dbus/dbus-connection.c41
-rw-r--r--dbus/dbus-connection.h8
-rw-r--r--dbus/dbus-dataslot.c100
-rw-r--r--dbus/dbus-dataslot.h16
-rw-r--r--dbus/dbus-server.c29
-rw-r--r--dbus/dbus-server.h4
-rw-r--r--glib/dbus-gmain.c24
-rw-r--r--glib/test-thread-server.c5
14 files changed, 194 insertions, 297 deletions
diff --git a/ChangeLog b/ChangeLog
index 377ceb44..b98f18c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2003-06-22 Havoc Pennington <hp@pobox.com>
+
+ * 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 <andersca@codefactory.se>
* configure.in: Add AM_PROG_GCJ and move AM_PROG_LIBTOOL
diff --git a/bus/bus.c b/bus/bus.c
index e86243a6..a5530974 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 70a0eb15..5121658d 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 8b2ba08e..d43e8121 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -32,8 +32,7 @@
#include <dbus/dbus-internals.h>
#include <string.h>
-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 f8d4c5f3..30cbcd05 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 dee9b9f7..6ab1eccc 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 d877a0b4..01b2a7bf 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 c2206cd3..9f4dd7ae 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 def864e4..defe9345 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 d4357325..6f591eb5 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 4007d7a5..1c9d53f0 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 5527f1ec..c2a0ca0f 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 c120a6c1..9b14049d 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 a92febf3..00044a79 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);