+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
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.
*/
}
(*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.
}
}
+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,
# 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))
}
/**
- * 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
*