SoupSession: make pause/unpause work in any state
authorDan Winship <danw@gnome.org>
Sun, 7 Aug 2011 22:50:14 +0000 (18:50 -0400)
committerDan Winship <danw@gnome.org>
Thu, 29 Sep 2011 14:36:23 +0000 (10:36 -0400)
https://bugzilla.gnome.org/show_bug.cgi?id=651146

libsoup/soup-message-queue.h
libsoup/soup-session-async.c
libsoup/soup-session-sync.c
libsoup/soup-session.c
libsoup/soup-session.h

index 08cc6df..43cb0ae 100644 (file)
@@ -45,7 +45,8 @@ struct _SoupMessageQueueItem {
        SoupURI *proxy_uri;
        SoupConnection *conn;
 
-       guint redirection_count;
+       guint paused            : 1;
+       guint redirection_count : 31;
 
        SoupMessageQueueItemState state;
 
index 661883b..c4684d7 100644 (file)
@@ -39,6 +39,7 @@ static void  queue_message   (SoupSession *session, SoupMessage *req,
 static guint send_message    (SoupSession *session, SoupMessage *req);
 static void  cancel_message  (SoupSession *session, SoupMessage *msg,
                              guint status_code);
+static void  kick            (SoupSession *session);
 
 static void  auth_required   (SoupSession *session, SoupMessage *msg,
                              SoupAuth *auth, gboolean retrying);
@@ -80,6 +81,7 @@ soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class)
        session_class->send_message = send_message;
        session_class->cancel_message = cancel_message;
        session_class->auth_required = auth_required;
+       session_class->kick = kick;
 
        object_class->finalize = finalize;
 }
@@ -359,6 +361,9 @@ process_queue_item (SoupMessageQueueItem *item,
        SoupProxyURIResolver *proxy_resolver;
 
        do {
+               if (item->paused)
+                       return;
+
                switch (item->state) {
                case SOUP_MESSAGE_STARTING:
                        proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, item->msg);
@@ -575,3 +580,9 @@ auth_required (SoupSession *session, SoupMessage *msg,
                        auth_required (session, msg, auth, retrying);
        }
 }
+
+static void
+kick (SoupSession *session)
+{
+       do_idle_run_queue (session);
+}
index 373b1bd..aecbf6f 100644 (file)
@@ -61,6 +61,7 @@ static void  cancel_message (SoupSession *session, SoupMessage *msg,
 static void  auth_required  (SoupSession *session, SoupMessage *msg,
                             SoupAuth *auth, gboolean retrying);
 static void  flush_queue    (SoupSession *session);
+static void  kick           (SoupSession *session);
 
 G_DEFINE_TYPE (SoupSessionSync, soup_session_sync, SOUP_TYPE_SESSION)
 
@@ -98,6 +99,7 @@ soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class)
        session_class->cancel_message = cancel_message;
        session_class->auth_required = auth_required;
        session_class->flush_queue = flush_queue;
+       session_class->kick = kick;
 
        object_class->finalize = finalize;
 }
@@ -249,6 +251,13 @@ process_queue_item (SoupMessageQueueItem *item)
 
        item->state = SOUP_MESSAGE_STARTING;
        do {
+               if (item->paused) {
+                       g_mutex_lock (priv->lock);
+                       while (item->paused)
+                               g_cond_wait (priv->cond, priv->lock);
+                       g_mutex_unlock (priv->lock);
+               }
+
                switch (item->state) {
                case SOUP_MESSAGE_STARTING:
                        proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, msg);
@@ -454,3 +463,13 @@ flush_queue (SoupSession *session)
 
        g_hash_table_destroy (current);
 }
+
+static void
+kick (SoupSession *session)
+{
+       SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session);
+
+       g_mutex_lock (priv->lock);
+       g_cond_broadcast (priv->cond);
+       g_mutex_unlock (priv->lock);
+}
index 3fc37fd..aa57d12 100644 (file)
@@ -1698,10 +1698,20 @@ void
 soup_session_pause_message (SoupSession *session,
                            SoupMessage *msg)
 {
+       SoupSessionPrivate *priv;
+       SoupMessageQueueItem *item;
+
        g_return_if_fail (SOUP_IS_SESSION (session));
        g_return_if_fail (SOUP_IS_MESSAGE (msg));
 
-       soup_message_io_pause (msg);
+       priv = SOUP_SESSION_GET_PRIVATE (session);
+       item = soup_message_queue_lookup (priv->queue, msg);
+       g_return_if_fail (item != NULL);
+
+       item->paused = TRUE;
+       if (item->state == SOUP_MESSAGE_RUNNING)
+               soup_message_io_pause (msg);
+       soup_message_queue_item_unref (item);
 }
 
 /**
@@ -1720,10 +1730,22 @@ void
 soup_session_unpause_message (SoupSession *session,
                              SoupMessage *msg)
 {
+       SoupSessionPrivate *priv;
+       SoupMessageQueueItem *item;
+
        g_return_if_fail (SOUP_IS_SESSION (session));
        g_return_if_fail (SOUP_IS_MESSAGE (msg));
 
-       soup_message_io_unpause (msg);
+       priv = SOUP_SESSION_GET_PRIVATE (session);
+       item = soup_message_queue_lookup (priv->queue, msg);
+       g_return_if_fail (item != NULL);
+
+       item->paused = FALSE;
+       if (item->state == SOUP_MESSAGE_RUNNING)
+               soup_message_io_unpause (msg);
+       soup_message_queue_item_unref (item);
+
+       SOUP_SESSION_GET_CLASS (session)->kick (session);
 }
 
 
index 4b6661f..7ad1d16 100644 (file)
@@ -51,8 +51,9 @@ typedef struct {
 
        void  (*flush_queue)     (SoupSession *session);
 
+       void  (*kick)            (SoupSession *session);
+
        /* Padding for future expansion */
-       void (*_libsoup_reserved3) (void);
        void (*_libsoup_reserved4) (void);
 } SoupSessionClass;