2003-06-22 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 22 Jun 2003 19:39:47 +0000 (19:39 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 22 Jun 2003 19:39:47 +0000 (19:39 +0000)
* 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

14 files changed:
ChangeLog
bus/bus.c
bus/connection.c
bus/dispatch.c
bus/test.c
dbus/dbus-bus.c
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-dataslot.c
dbus/dbus-dataslot.h
dbus/dbus-server.c
dbus/dbus-server.h
glib/dbus-gmain.c
glib/test-thread-server.c

index 377ceb4..b98f18c 100644 (file)
--- 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
index e86243a..a553097 100644 (file)
--- 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);
     }
 }
 
index 70a0eb1..5121658 100644 (file)
@@ -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);
     }
 }
 
index 8b2ba08..d43e812 100644 (file)
@@ -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;
     }
index f8d4c5f..30cbcd0 100644 (file)
@@ -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;
     }
   
index dee9b9f..6ab1ecc 100644 (file)
@@ -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;
index d877a0b..01b2a7b 100644 (file)
@@ -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;
 
index c2206cd..9f4dd7a 100644 (file)
@@ -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); 
 
index def864e..defe934 100644 (file)
@@ -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;
     }
 
index d435732..6f591eb 100644 (file)
@@ -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,
index 4007d7a..1c9d53f 100644 (file)
@@ -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);
 }
 
 /**
index 5527f1e..c2a0ca0 100644 (file)
@@ -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,
index c120a6c..9b14049 100644 (file)
@@ -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;
 
index a92febf..00044a7 100644 (file)
@@ -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);