[libsoup/carlosgc/priority-changes: 1/2] session: add support for re-prioritizing queue items




commit be0586f43a3ade67b15baa8e9cf03a2033ad37b5
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Tue Jun 1 11:53:08 2021 +0200

    session: add support for re-prioritizing queue items
    
    Monitor SoupMessage:priority changes to sort the queue accortding to the
    new message priorities.

 libsoup/soup-message-queue-item.c |  1 -
 libsoup/soup-message-queue-item.h |  1 -
 libsoup/soup-session.c            | 32 +++++++++++++++++++++++++++-
 tests/session-test.c              | 45 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 3 deletions(-)
---
diff --git a/libsoup/soup-message-queue-item.c b/libsoup/soup-message-queue-item.c
index 71c77054..42bd865d 100644
--- a/libsoup/soup-message-queue-item.c
+++ b/libsoup/soup-message-queue-item.c
@@ -26,7 +26,6 @@ soup_message_queue_item_new (SoupSession        *session,
         item->msg = g_object_ref (msg);
         item->async = async;
         item->cancellable = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
-        item->priority = soup_message_get_priority (msg);
 
         g_signal_connect_swapped (msg, "restarted",
                                   G_CALLBACK (g_cancellable_reset),
diff --git a/libsoup/soup-message-queue-item.h b/libsoup/soup-message-queue-item.h
index f7d72ccb..cb483668 100644
--- a/libsoup/soup-message-queue-item.h
+++ b/libsoup/soup-message-queue-item.h
@@ -38,7 +38,6 @@ struct _SoupMessageQueueItem {
         guint io_started   : 1;
         guint async        : 1;
         guint connect_only : 1;
-        guint priority     : 3;
         guint resend_count : 5;
         int io_priority;
 
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index d74e26dc..b3fbea5f 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -107,6 +107,8 @@ typedef struct {
 
        GQueue *queue;
        GSource *queue_source;
+        guint16 in_async_run_queue;
+        gboolean needs_queue_sort;
 
        char *user_agent;
        char *accept_language;
@@ -1323,8 +1325,27 @@ static int
 compare_queue_item (SoupMessageQueueItem *a,
                    SoupMessageQueueItem *b)
 {
+        SoupMessagePriority a_priority = soup_message_get_priority (a->msg);
+        SoupMessagePriority b_priority = soup_message_get_priority (b->msg);
+
        /* For the same priority we want to append items in the queue */
-       return b->priority > a->priority ? 1 : -1;
+       return b_priority > a_priority ? 1 : -1;
+}
+
+static void
+message_priority_changed (SoupMessage          *msg,
+                          GParamSpec           *pspec,
+                          SoupMessageQueueItem *item)
+{
+        SoupSessionPrivate *priv = soup_session_get_instance_private (item->session);
+
+        if (priv->in_async_run_queue) {
+                priv->needs_queue_sort = TRUE;
+                return;
+        }
+
+        g_queue_sort (priv->queue, (GCompareDataFunc)compare_queue_item, NULL);
+        priv->needs_queue_sort = FALSE;
 }
 
 static SoupMessageQueueItem *
@@ -1359,6 +1380,8 @@ soup_session_append_queue_item (SoupSession        *session,
                                               G_CALLBACK (misdirected_handler), item);
        g_signal_connect (msg, "restarted",
                          G_CALLBACK (message_restarted), item);
+        g_signal_connect (msg, "notify::priority",
+                          G_CALLBACK (message_priority_changed), item);
 
        for (f = priv->features; f; f = g_slist_next (f)) {
                SoupSessionFeature *feature = SOUP_SESSION_FEATURE (f->data);
@@ -2054,6 +2077,7 @@ async_run_queue (SoupSession *session)
        gboolean try_cleanup = TRUE, should_cleanup = FALSE;
 
        g_object_ref (session);
+        priv->in_async_run_queue++;
        soup_session_cleanup_connections (session, FALSE);
 
  try_again:
@@ -2070,6 +2094,12 @@ async_run_queue (SoupSession *session)
                }
        }
 
+        priv->in_async_run_queue--;
+        if (!priv->in_async_run_queue && priv->needs_queue_sort) {
+                g_queue_sort (priv->queue, (GCompareDataFunc)compare_queue_item, NULL);
+                priv->needs_queue_sort = FALSE;
+        }
+
        g_object_unref (session);
 }
 
diff --git a/tests/session-test.c b/tests/session-test.c
index 4a1596b3..1c51600c 100644
--- a/tests/session-test.c
+++ b/tests/session-test.c
@@ -230,6 +230,50 @@ do_priority_tests (void)
        soup_test_session_abort_unref (session);
 }
 
+static void
+do_priority_change_test (void)
+{
+        SoupSession *session;
+        SoupMessage *msgs[3];
+        int i, finished_count = 0;
+        SoupMessagePriority priorities[] =
+                { SOUP_MESSAGE_PRIORITY_LOW,
+                  SOUP_MESSAGE_PRIORITY_HIGH,
+                  SOUP_MESSAGE_PRIORITY_NORMAL };
+
+        session = soup_test_session_new ("max-conns", 1, NULL);
+
+        expected_priorities[0] = SOUP_MESSAGE_PRIORITY_HIGH;
+        expected_priorities[1] = SOUP_MESSAGE_PRIORITY_LOW;
+        expected_priorities[2] = SOUP_MESSAGE_PRIORITY_VERY_LOW;
+
+        for (i = 0; i < 3; i++) {
+                GUri *msg_uri;
+                char buf[5];
+
+                g_snprintf (buf, sizeof (buf), "%d", i);
+                msg_uri = g_uri_parse_relative (base_uri, buf, SOUP_HTTP_URI_FLAGS, NULL);
+                msgs[i] = soup_message_new_from_uri ("GET", msg_uri);
+                g_uri_unref (msg_uri);
+
+                soup_message_set_priority (msgs[i], priorities[i]);
+                g_signal_connect (msgs[i], "finished",
+                                  G_CALLBACK (priority_test_finished_cb), &finished_count);
+                soup_session_send_async (session, msgs[i], G_PRIORITY_DEFAULT, NULL, NULL, NULL);
+        }
+
+        soup_message_set_priority (msgs[2], SOUP_MESSAGE_PRIORITY_VERY_LOW);
+
+        debug_printf (2, "    waiting for finished\n");
+        while (finished_count != 3)
+                g_main_context_iteration (NULL, TRUE);
+
+        for (i = 0; i < 3; i++)
+                g_object_unref (msgs[i]);
+
+        soup_test_session_abort_unref (session);
+}
+
 static void
 test_session_properties (const char *name,
                         SoupSession *session,
@@ -437,6 +481,7 @@ main (int argc, char **argv)
 
        g_test_add_func ("/session/SoupSession", do_plain_tests);
        g_test_add_func ("/session/priority", do_priority_tests);
+        g_test_add_func ("/session/priority-change", do_priority_change_test);
        g_test_add_func ("/session/property", do_property_tests);
        g_test_add_func ("/session/features", do_features_test);
        g_test_add_func ("/session/queue-order", do_queue_order_test);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]