diff options
author | Dan Winship <danw@gnome.org> | 2013-12-10 12:06:34 +0100 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2014-11-02 10:23:26 -0500 |
commit | 1488f5f9a777c11abf5c03feec33507ddb5563b6 (patch) | |
tree | 20ce219fc4d3ec356156724a1ec7e08dcf713977 | |
parent | 09adf1aeb7c1521fc35238489dddd29f13ef4357 (diff) | |
download | libsoup-1488f5f9a777c11abf5c03feec33507ddb5563b6.tar.gz |
get rid of SoupSessionPrivate->conns hash
-rw-r--r-- | libsoup/soup-session-host.c | 81 | ||||
-rw-r--r-- | libsoup/soup-session-host.h | 3 | ||||
-rw-r--r-- | libsoup/soup-session.c | 90 |
3 files changed, 108 insertions, 66 deletions
diff --git a/libsoup/soup-session-host.c b/libsoup/soup-session-host.c index ff45a12f..2dfda6c6 100644 --- a/libsoup/soup-session-host.c +++ b/libsoup/soup-session-host.c @@ -19,6 +19,8 @@ G_DEFINE_TYPE (SoupSessionHost, soup_session_host, G_TYPE_OBJECT) typedef struct { + GMutex mutex; + SoupURI *uri; SoupAddress *addr; @@ -47,6 +49,9 @@ static guint signals[LAST_SIGNAL] = { 0 }; static void soup_session_host_init (SoupSessionHost *host) { + SoupSessionHostPrivate *priv = SOUP_SESSION_HOST_GET_PRIVATE (host); + + g_mutex_init (&priv->mutex); } static void @@ -64,6 +69,8 @@ soup_session_host_finalize (GObject *object) soup_uri_free (priv->uri); g_object_unref (priv->addr); + g_mutex_clear (&priv->mutex); + G_OBJECT_CLASS (soup_session_host_parent_class)->finalize (object); } @@ -146,6 +153,30 @@ emit_unused (gpointer host) return FALSE; } +static void +connection_disconnected (SoupConnection *conn, gpointer host) +{ + SoupSessionHostPrivate *priv = SOUP_SESSION_HOST_GET_PRIVATE (host); + + g_mutex_lock (&priv->mutex); + + if (soup_connection_get_ssl_fallback (conn)) + priv->ssl_fallback = TRUE; + + priv->connections = g_slist_remove (priv->connections, conn); + priv->num_conns--; + + if (priv->num_conns == 0) { + g_assert (priv->keep_alive_src == NULL); + priv->keep_alive_src = soup_add_timeout_reffed (soup_session_get_async_context (priv->session), + HOST_KEEP_ALIVE, + emit_unused, + host); + } + + g_mutex_unlock (&priv->mutex); +} + SoupConnection * soup_session_host_get_connection (SoupSessionHost *host, gboolean need_new_connection, @@ -158,11 +189,14 @@ soup_session_host_get_connection (SoupSessionHost *host, int num_pending = 0; SoupSocketProperties *socket_props; + g_mutex_lock (&priv->mutex); + for (conns = priv->connections; conns; conns = conns->next) { conn = conns->data; if (!need_new_connection && soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) { soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + g_mutex_unlock (&priv->mutex); return conn; } else if (soup_connection_get_state (conn) == SOUP_CONNECTION_CONNECTING) num_pending++; @@ -171,17 +205,21 @@ soup_session_host_get_connection (SoupSessionHost *host, /* Limit the number of pending connections; num_messages / 2 * is somewhat arbitrary... */ - if (num_pending > priv->num_messages / 2) + if (num_pending > priv->num_messages / 2) { + g_mutex_unlock (&priv->mutex); return NULL; + } if (priv->num_conns >= priv->max_conns) { if (need_new_connection) *try_cleanup = TRUE; + g_mutex_unlock (&priv->mutex); return NULL; } if (at_max_conns) { *try_cleanup = TRUE; + g_mutex_unlock (&priv->mutex); return NULL; } @@ -198,40 +236,41 @@ soup_session_host_get_connection (SoupSessionHost *host, priv->num_conns++; priv->connections = g_slist_prepend (priv->connections, conn); + g_signal_connect (conn, "disconnected", + G_CALLBACK (connection_disconnected), + host); + if (priv->keep_alive_src) { g_source_destroy (priv->keep_alive_src); g_source_unref (priv->keep_alive_src); priv->keep_alive_src = NULL; } + g_mutex_unlock (&priv->mutex); return conn; } -void -soup_session_host_remove_connection (SoupSessionHost *host, - SoupConnection *conn) +int +soup_session_host_get_num_connections (SoupSessionHost *host) { - SoupSessionHostPrivate *priv = SOUP_SESSION_HOST_GET_PRIVATE (host); + return SOUP_SESSION_HOST_GET_PRIVATE (host)->num_conns; +} - if (soup_connection_get_ssl_fallback (conn)) - priv->ssl_fallback = TRUE; +GSList * +soup_session_host_get_connections (SoupSessionHost *host) +{ + SoupSessionHostPrivate *priv = SOUP_SESSION_HOST_GET_PRIVATE (host); + GSList *conns, *c; - priv->connections = g_slist_remove (priv->connections, conn); - priv->num_conns--; + g_mutex_lock (&priv->mutex); - if (priv->num_conns == 0) { - g_assert (priv->keep_alive_src == NULL); - priv->keep_alive_src = soup_add_timeout_reffed (soup_session_get_async_context (priv->session), - HOST_KEEP_ALIVE, - emit_unused, - host); - } -} + conns = NULL; + for (c = priv->connections; c; c = c->next) + conns = g_slist_prepend (conns, g_object_ref (c->data)); + conns = g_slist_reverse (conns); -int -soup_session_host_get_num_connections (SoupSessionHost *host) -{ - return SOUP_SESSION_HOST_GET_PRIVATE (host)->num_conns; + g_mutex_unlock (&priv->mutex); + return conns; } gboolean diff --git a/libsoup/soup-session-host.h b/libsoup/soup-session-host.h index fecd5d23..4f27b50d 100644 --- a/libsoup/soup-session-host.h +++ b/libsoup/soup-session-host.h @@ -44,9 +44,8 @@ SoupConnection *soup_session_host_get_connection (SoupSessionHost *ho gboolean need_new_connection, gboolean at_max_conns, gboolean *try_cleanup); -void soup_session_host_remove_connection (SoupSessionHost *host, - SoupConnection *conn); int soup_session_host_get_num_connections (SoupSessionHost *host); +GSList *soup_session_host_get_connections (SoupSessionHost *host); gboolean soup_session_host_get_ssl_fallback (SoupSessionHost *host); void soup_session_host_set_ssl_fallback (SoupSessionHost *host, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index d5c8a404..b4261b69 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -117,7 +117,6 @@ typedef struct { GHashTable *features_cache; GHashTable *http_hosts, *https_hosts; /* char* -> SoupSessionHost */ - GHashTable *conns; /* SoupConnection -> SoupSessionHost */ guint num_conns; guint max_conns, max_conns_per_host; @@ -146,8 +145,7 @@ typedef struct { static void connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data); static void connection_disconnected (SoupConnection *conn, gpointer user_data); -static void drop_connection (SoupSession *session, SoupSessionHost *host, - SoupConnection *conn); +static void drop_connection (SoupSession *session, SoupConnection *conn); static void auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth, @@ -229,7 +227,6 @@ soup_session_init (SoupSession *session) priv->https_hosts = g_hash_table_new_full (soup_host_uri_hash, soup_host_uri_equal, NULL, g_object_unref); - priv->conns = g_hash_table_new (NULL, NULL); priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT; priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT; @@ -318,7 +315,6 @@ soup_session_dispose (GObject *object) priv->disposed = TRUE; soup_session_abort (session); - g_warn_if_fail (g_hash_table_size (priv->conns) == 0); while (priv->features) soup_session_remove_feature (session, priv->features->data); @@ -338,7 +334,6 @@ soup_session_finalize (GObject *object) g_cond_clear (&priv->conn_cond); g_hash_table_destroy (priv->http_hosts); g_hash_table_destroy (priv->https_hosts); - g_hash_table_destroy (priv->conns); g_free (priv->user_agent); g_free (priv->accept_language); @@ -1297,38 +1292,64 @@ soup_session_send_queue_item (SoupSession *session, soup_connection_send_request (item->conn, item, completion_cb, item); } +/* Requires conn_lock to be locked */ +static GSList * +get_all_connections (SoupSession *session) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + GSList *conns = NULL, *host_conns; + GHashTableIter iter; + gpointer host; + + g_hash_table_iter_init (&iter, priv->http_hosts); + while (g_hash_table_iter_next (&iter, NULL, &host)) { + host_conns = soup_session_host_get_connections (host); + conns = g_slist_concat (host_conns, conns); + } + g_hash_table_iter_init (&iter, priv->https_hosts); + while (g_hash_table_iter_next (&iter, NULL, &host)) { + host_conns = soup_session_host_get_connections (host); + conns = g_slist_concat (host_conns, conns); + } + + return conns; +} + static gboolean soup_session_cleanup_connections (SoupSession *session, gboolean cleanup_idle) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - GSList *conns = NULL, *c; - GHashTableIter iter; - gpointer conn, host; + GSList *conns, *disconnect_conns, *c; + SoupConnection *conn; SoupConnectionState state; g_mutex_lock (&priv->conn_lock); - g_hash_table_iter_init (&iter, priv->conns); - while (g_hash_table_iter_next (&iter, &conn, &host)) { + + conns = get_all_connections (session); + disconnect_conns = NULL; + for (c = conns; c; c = c->next) { + conn = c->data; state = soup_connection_get_state (conn); if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED || (cleanup_idle && state == SOUP_CONNECTION_IDLE)) { - conns = g_slist_prepend (conns, g_object_ref (conn)); - g_hash_table_iter_remove (&iter); - drop_connection (session, host, conn); - } + disconnect_conns = g_slist_prepend (disconnect_conns, conn); + drop_connection (session, conn); + } else + g_object_unref (conn); } + g_slist_free (conns); g_mutex_unlock (&priv->conn_lock); - if (!conns) + if (!disconnect_conns) return FALSE; - for (c = conns; c; c = c->next) { + for (c = disconnect_conns; c; c = c->next) { conn = c->data; soup_connection_disconnect (conn); g_object_unref (conn); } - g_slist_free (conns); + g_slist_free (disconnect_conns); return TRUE; } @@ -1361,18 +1382,12 @@ free_unused_host (SoupSessionHost *host, g_mutex_unlock (&priv->conn_lock); } +/* Requires conn_lock to be locked */ static void -drop_connection (SoupSession *session, SoupSessionHost *host, SoupConnection *conn) +drop_connection (SoupSession *session, SoupConnection *conn) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - /* Note: caller must hold conn_lock, and must remove @conn - * from priv->conns itself. - */ - - if (host) - soup_session_host_remove_connection (host, conn); - g_signal_handlers_disconnect_by_func (conn, connection_disconnected, session); g_signal_handlers_disconnect_by_func (conn, connection_state_changed, session); priv->num_conns--; @@ -1385,14 +1400,10 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) { SoupSession *session = user_data; SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupSessionHost *host; g_mutex_lock (&priv->conn_lock); - host = g_hash_table_lookup (priv->conns, conn); - if (host) - g_hash_table_remove (priv->conns, conn); - drop_connection (session, host, conn); + drop_connection (session, conn); g_mutex_unlock (&priv->conn_lock); @@ -1757,8 +1768,6 @@ get_connection_for_host (SoupSession *session, * conn_lock. */ g_signal_emit (session, signals[CONNECTION_CREATED], 0, conn); - - g_hash_table_insert (priv->conns, conn, host); priv->num_conns++; } @@ -2389,8 +2398,6 @@ soup_session_abort (SoupSession *session) { SoupSessionPrivate *priv; GSList *conns, *c; - GHashTableIter iter; - gpointer conn, host; g_return_if_fail (SOUP_IS_SESSION (session)); priv = SOUP_SESSION_GET_PRIVATE (session); @@ -2399,18 +2406,15 @@ soup_session_abort (SoupSession *session) /* Close all idle connections */ g_mutex_lock (&priv->conn_lock); - conns = NULL; - g_hash_table_iter_init (&iter, priv->conns); - while (g_hash_table_iter_next (&iter, &conn, &host)) { + conns = get_all_connections (session); + for (c = conns; c; c = c->next) { + SoupConnection *conn = c->data; SoupConnectionState state; state = soup_connection_get_state (conn); if (state == SOUP_CONNECTION_IDLE || - state == SOUP_CONNECTION_REMOTE_DISCONNECTED) { - conns = g_slist_prepend (conns, g_object_ref (conn)); - g_hash_table_iter_remove (&iter); - drop_connection (session, host, conn); - } + state == SOUP_CONNECTION_REMOTE_DISCONNECTED) + drop_connection (session, conn); } g_mutex_unlock (&priv->conn_lock); |