summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang Fan <sfanxiang@gmail.com>2019-02-14 10:58:10 +0800
committerCarlos Soriano <csoriano1618+gnome@gmail.com>2019-02-22 15:11:55 +0000
commit905657de54daa0287c047dacc028ed9841216126 (patch)
tree1f19bec0a5056ede0c3339808696e05ef6898c43
parente03376b9d84480bf9596fb551fa94d101e9dd4ce (diff)
downloadnautilus-905657de54daa0287c047dacc028ed9841216126.tar.gz
nautilus-search-engine-simple: Only spawn one idle each time
To avoid clogging up the main loop.
-rw-r--r--src/nautilus-search-engine-simple.c126
1 files 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;
}