Consider existing addresses with a zero refcount valid to return (with an
authorAlex Graveley <alex@ximian.com>
Tue, 30 Oct 2001 05:40:00 +0000 (05:40 +0000)
committerAlex Graveley <orph@src.gnome.org>
Tue, 30 Oct 2001 05:40:00 +0000 (05:40 +0000)
2001-10-30  Alex Graveley  <alex@ximian.com>

* src/libsoup/soup-socket-unix.c (soup_address_new): Consider
existing addresses with a zero refcount valid to return (with an
added refcount).
(prune_zeroref_addresses_foreach): Impl.
(prune_zeroref_addresses_timeout): Impl.
(soup_address_unref): Don't free zero ref addresses, instead make
sure zeroref timeout handler is installed and install if not. Also
move to here from soup-socket.c.

* src/libsoup/soup-private.h: Add killme flag to soup_address.

* src/libsoup/soup-socket-win.c (soup_address_unref): Move here
from soup-socket.c.

ChangeLog
libsoup/soup-private.h
libsoup/soup-socket-unix.c
libsoup/soup-socket.c

index 1a8efe9..d23a2fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2001-10-30  Alex Graveley  <alex@ximian.com>
+
+       * src/libsoup/soup-socket-unix.c (soup_address_new): Consider
+       existing addresses with a zero refcount valid to return (with an
+       added refcount).
+       (prune_zeroref_addresses_foreach): Impl.
+       (prune_zeroref_addresses_timeout): Impl.
+       (soup_address_unref): Don't free zero ref addresses, instead make
+       sure zeroref timeout handler is installed and install if not. Also
+       move to here from soup-socket.c.
+
+       * src/libsoup/soup-private.h: Add killme flag to soup_address.
+
+       * src/libsoup/soup-socket-win.c (soup_address_unref): Move here
+       from soup-socket.c.
+
 2001-10-29  Alex Graveley  <alex@ximian.com>
 
        * src/libsoup/soup-message.c (authorize_handler): Call
index 04f4e1c..2247d5c 100644 (file)
@@ -82,6 +82,7 @@ struct _SoupAddress {
        gchar*          name;
        struct sockaddr sa;
        gint            ref_count;
+       gboolean        killme;
 };
 
 struct _SoupSocket {
index 417bf4e..ceb803b 100644 (file)
@@ -597,7 +597,7 @@ soup_address_new (const gchar* name,
        else {
                ia = g_hash_table_lookup (active_address_hash, name);
 
-               if (ia && ia->ref_count > 0) {
+               if (ia && ia->ref_count >= 0) {
                        /*
                         * Existing valid request, use it.
                         */
@@ -614,8 +614,10 @@ soup_address_new (const gchar* name,
                        }
 
                        (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
+
                        return NULL;
-               } else if (ia && soup_address_get_port (ia) == port) {
+               } 
+               else if (ia && soup_address_get_port (ia) == port) {
                        /*
                         * Lookup currently in progress.
                         * Add func to list of callbacks in state.
@@ -815,6 +817,95 @@ soup_address_new_cancel (SoupAddressNewId id)
        }
 }
 
+static gboolean 
+prune_zeroref_addresses_foreach (gchar       *hostname,
+                                SoupAddress *ia,
+                                gint        *remaining)
+{
+       /*
+        * References exist, clear kill flag.
+        */
+       if (ia->ref_count != 0) {
+               ia->killme = FALSE;
+               return FALSE;
+       }
+
+       /*
+        * Kill if marked.  Otherwise mark.
+        */
+       if (ia->killme) {
+               g_free (ia->name);
+               g_free (ia);
+               return TRUE;
+       } else
+               ia->killme = TRUE;
+
+       /*
+        * Make sure the timeout stays around
+        */
+       (*remaining)++;
+
+       return FALSE;
+}
+
+static guint zeroref_address_timeout_tag = 0;
+
+static gboolean 
+prune_zeroref_addresses_timeout (gpointer not_used)
+{
+       gint remaining = 0;
+
+       /*
+        * Remove all marked addresses, mark zero references.
+        */
+       g_hash_table_foreach_remove (active_address_hash, 
+                                    (GHRFunc) prune_zeroref_addresses_foreach,
+                                    &remaining);
+
+       /*
+        * No new marks, so remove timeout handler
+        */
+       if (remaining == 0) {
+               zeroref_address_timeout_tag = 0;
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
+ * soup_address_unref
+ * @ia: SoupAddress to unreference
+ *
+ * Remove a reference from the SoupAddress.  When reference count
+ * reaches 0, the address is deleted.
+ **/
+void
+soup_address_unref (SoupAddress* ia)
+{
+       g_return_if_fail (ia != NULL);
+
+       --ia->ref_count;
+
+       if (ia->ref_count == 0) {
+               if (!zeroref_address_timeout_tag) {
+                       /* 
+                        * Cleanup zero reference addresses every 2 minutes.
+                        *
+                        * This involves an initial sweep to mark zero reference
+                        * addresses, then on the next sweep marked addresses
+                        * still not referenced are freed.
+                        */
+                       zeroref_address_timeout_tag = 
+                               g_timeout_add (120000, 
+                                              (GSourceFunc) 
+                                              prune_zeroref_addresses_timeout,
+                                              NULL);
+                               return;
+               }
+       }
+}
+
 static gboolean
 soup_address_get_name_cb (GIOChannel* iochannel,
                          GIOCondition condition,
index 06c59ce..f881471 100644 (file)
@@ -38,7 +38,6 @@
 #  endif
 #  define SOUP_CLOSE_SOCKET(fd) close(fd)
 #  define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_unix_new(fd)
-   extern GHashTable *active_address_hash;
 #endif
 
 #define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
@@ -90,31 +89,6 @@ soup_address_ref (SoupAddress* ia)
 }
 
 /**
- * soup_address_unref
- * @ia: SoupAddress to unreference
- *
- * Remove a reference from the SoupAddress.  When reference count
- * reaches 0, the address is deleted.
- **/
-void
-soup_address_unref (SoupAddress* ia)
-{
-       g_return_if_fail (ia != NULL);
-
-       --ia->ref_count;
-
-       if (ia->ref_count == 0) {
-               if (ia->name != NULL) {
-#ifndef SOUP_WIN32
-                       g_hash_table_remove (active_address_hash, ia->name);
-#endif
-                       g_free (ia->name);
-               }
-               g_free (ia);
-       }
-}
-
-/**
  * soup_address_copy
  * @ia: SoupAddress to copy
  *