[nautilus] nautilus-search-engine-simple: Only spawn one idle each time



commit 905657de54daa0287c047dacc028ed9841216126
Author: Xiang Fan <sfanxiang gmail com>
Date:   Thu Feb 14 10:58:10 2019 +0800

    nautilus-search-engine-simple: Only spawn one idle each time
    
    To avoid clogging up the main loop.

 src/nautilus-search-engine-simple.c | 126 +++++++++++++++++++++++++++++-------
 1 file changed, 103 insertions(+), 23 deletions(-)
---
diff --git a/src/nautilus-search-engine-simple.c b/src/nautilus-search-engine-simple.c
index 8def0a644..1318cbdec 100644
--- a/src/nautilus-search-engine-simple.c
+++ b/src/nautilus-search-engine-simple.c
@@ -58,6 +58,9 @@ typedef struct
     GList *hits;
 
     NautilusQuery *query;
+
+    GMutex idle_mutex;
+    GQueue *idle_queue;
 } SearchThreadData;
 
 
@@ -107,6 +110,9 @@ search_thread_data_new (NautilusSearchEngineSimple *engine,
 
     data->cancellable = g_cancellable_new ();
 
+    g_mutex_init (&data->idle_mutex);
+    data->idle_queue = g_queue_new ();
+
     return data;
 }
 
@@ -122,14 +128,15 @@ search_thread_data_free (SearchThreadData *data)
     g_clear_pointer (&data->mime_types, g_ptr_array_unref);
     g_list_free_full (data->hits, g_object_unref);
     g_object_unref (data->engine);
+    g_mutex_clear (&data->idle_mutex);
+    g_queue_free (data->idle_queue);
 
     g_free (data);
 }
 
-static gboolean
-search_thread_done_idle (gpointer user_data)
+static void
+search_thread_done_idle (SearchThreadData *data)
 {
-    SearchThreadData *data = user_data;
     NautilusSearchEngineSimple *engine = data->engine;
 
     if (g_cancellable_is_cancelled (data->cancellable))
@@ -147,48 +154,121 @@ search_thread_done_idle (gpointer user_data)
     g_object_notify (G_OBJECT (engine), "running");
 
     search_thread_data_free (data);
+}
 
-    return FALSE;
+static void
+search_thread_process_hits_idle (SearchThreadData *data, GList *hits)
+{
+    if (!g_cancellable_is_cancelled (data->cancellable))
+    {
+        DEBUG ("Simple engine add hits");
+        nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (data->engine),
+                                             hits);
+    }
 }
 
 typedef struct
 {
-    GList *hits;
+    gboolean clean_up;  /* Whether we are done and should clean up */
+    GList *hits;        /* Must be a valid list when clean_up is not set,
+                         * otherwise unused */
+} IdleQueueData;
+
+static gboolean
+search_thread_idle (gpointer user_data)
+{
     SearchThreadData *thread_data;
-} SearchHitsData;
+    IdleQueueData *queue_data;
+    gboolean is_last;
 
+    thread_data = user_data;
 
-static gboolean
-search_thread_add_hits_idle (gpointer user_data)
+    g_mutex_lock (&thread_data->idle_mutex);
+    queue_data = g_queue_pop_head (thread_data->idle_queue);
+    if (queue_data)
+    {
+        is_last = g_queue_is_empty (thread_data->idle_queue);
+        g_mutex_unlock (&thread_data->idle_mutex);
+
+        if (!queue_data->clean_up)
+        {
+            search_thread_process_hits_idle (thread_data, queue_data->hits);
+            g_list_free_full (queue_data->hits, g_object_unref);
+            g_free (queue_data);
+
+            return is_last ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE;
+        }
+        else
+        {
+            search_thread_done_idle (thread_data);
+            g_free (queue_data);
+        }
+    }
+    else
+    {
+        g_mutex_unlock (&thread_data->idle_mutex);
+    }
+
+    return G_SOURCE_REMOVE;
+}
+
+/* Do not directly call this function.
+ * Use start_idle_processing or start_idle_cleanup instead. */
+static void
+start_idle_processing_or_cleanup (SearchThreadData *thread_data,
+                                  GList            *hits,
+                                  gboolean          clean_up)
 {
-    SearchHitsData *data = user_data;
+    gboolean idle_stopped;
+    IdleQueueData *queue_data;
+
+    g_assert (hits || clean_up);
 
-    if (!g_cancellable_is_cancelled (data->thread_data->cancellable))
+    g_mutex_lock (&thread_data->idle_mutex);
+    idle_stopped = g_queue_is_empty (thread_data->idle_queue);
+    if (hits)
     {
-        DEBUG ("Simple engine add hits");
-        nautilus_search_provider_hits_added (NAUTILUS_SEARCH_PROVIDER (data->thread_data->engine),
-                                             data->hits);
+        queue_data = g_new (IdleQueueData, 1);
+        queue_data->clean_up = FALSE;
+        queue_data->hits = hits;
+        g_queue_push_tail (thread_data->idle_queue, queue_data);
     }
+    if (clean_up)
+    {
+        queue_data = g_new (IdleQueueData, 1);
+        queue_data->clean_up = TRUE;
+        queue_data->hits = NULL;
+        g_queue_push_tail (thread_data->idle_queue, queue_data);
+    }
+    g_mutex_unlock (&thread_data->idle_mutex);
 
-    g_list_free_full (data->hits, g_object_unref);
-    g_free (data);
+    if (idle_stopped)
+    {
+        g_idle_add (search_thread_idle, thread_data);
+    }
+}
 
-    return FALSE;
+static void
+start_idle_processing (SearchThreadData *thread_data,
+                       GList            *hits)
+{
+    start_idle_processing_or_cleanup (thread_data, hits, FALSE);
 }
 
 static void
-send_batch (SearchThreadData *thread_data)
+start_idle_cleanup (SearchThreadData *thread_data)
 {
-    SearchHitsData *data;
+    start_idle_processing_or_cleanup (thread_data, NULL, TRUE);
+}
 
+static void
+send_batch (SearchThreadData *thread_data)
+{
     thread_data->n_processed_files = 0;
 
     if (thread_data->hits)
     {
-        data = g_new (SearchHitsData, 1);
-        data->hits = thread_data->hits;
-        data->thread_data = thread_data;
-        g_idle_add (search_thread_add_hits_idle, data);
+        start_idle_processing (thread_data, thread_data->hits);
     }
     thread_data->hits = NULL;
 }
@@ -391,7 +471,7 @@ search_thread_func (gpointer user_data)
         send_batch (data);
     }
 
-    g_idle_add (search_thread_done_idle, data);
+    start_idle_cleanup (data);
 
     return NULL;
 }


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