[nautilus] search-engine-simple: Make some modifications to previous commit
- From: Carlos Soriano <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] search-engine-simple: Make some modifications to previous commit
- Date: Fri, 22 Feb 2019 15:22:41 +0000 (UTC)
commit 3a539ef131982d05454845d7ab7757a9fd1aedf2
Author: Carlos Soriano <csoriano redhat com>
Date: Thu Feb 21 16:52:30 2019 +0100
search-engine-simple: Make some modifications to previous commit
* Cleaner separation of phases
* Avoid some races
* Fix some leaks
src/nautilus-search-engine-simple.c | 131 +++++++++++++++++-------------------
1 file changed, 62 insertions(+), 69 deletions(-)
---
diff --git a/src/nautilus-search-engine-simple.c b/src/nautilus-search-engine-simple.c
index 1318cbdec..1687d218a 100644
--- a/src/nautilus-search-engine-simple.c
+++ b/src/nautilus-search-engine-simple.c
@@ -59,8 +59,12 @@ typedef struct
NautilusQuery *query;
+ gint processing_id;
GMutex idle_mutex;
+ // The following data can be accessed from different threads
+ // and needs to lock the mutex
GQueue *idle_queue;
+ gboolean finished;
} SearchThreadData;
@@ -119,6 +123,8 @@ search_thread_data_new (NautilusSearchEngineSimple *engine,
static void
search_thread_data_free (SearchThreadData *data)
{
+ GList *hits;
+
g_queue_foreach (data->directories,
(GFunc) g_object_unref, NULL);
g_queue_free (data->directories);
@@ -129,13 +135,18 @@ search_thread_data_free (SearchThreadData *data)
g_list_free_full (data->hits, g_object_unref);
g_object_unref (data->engine);
g_mutex_clear (&data->idle_mutex);
+
+ while ((hits = g_queue_pop_head (data->idle_queue)))
+ {
+ g_list_free_full (hits, g_object_unref);
+ }
g_queue_free (data->idle_queue);
g_free (data);
}
-static void
-search_thread_done_idle (SearchThreadData *data)
+static gboolean
+search_thread_done (SearchThreadData *data)
{
NautilusSearchEngineSimple *engine = data->engine;
@@ -154,6 +165,8 @@ search_thread_done_idle (SearchThreadData *data)
g_object_notify (G_OBJECT (engine), "running");
search_thread_data_free (data);
+
+ return G_SOURCE_REMOVE;
}
static void
@@ -167,108 +180,88 @@ search_thread_process_hits_idle (SearchThreadData *data, GList *hits)
}
}
-typedef struct
-{
- 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)
+search_thread_process_idle (gpointer user_data)
{
SearchThreadData *thread_data;
- IdleQueueData *queue_data;
- gboolean is_last;
+ GList *hits;
thread_data = user_data;
g_mutex_lock (&thread_data->idle_mutex);
- queue_data = g_queue_pop_head (thread_data->idle_queue);
- if (queue_data)
+ hits = g_queue_pop_head (thread_data->idle_queue);
+ // Even if the cancellable is cancelled, we need to make sure the search
+ // thread has aknowledge it, and therefore not using the thread data after
+ // freeing it. The search thread will mark as finished whenever the search
+ // is finished or cancelled.
+ // Nonetheless, we should stop yielding results if the search was cancelled
+ if (thread_data->finished)
{
- is_last = g_queue_is_empty (thread_data->idle_queue);
- g_mutex_unlock (&thread_data->idle_mutex);
-
- if (!queue_data->clean_up)
+ if (hits == NULL || g_cancellable_is_cancelled (thread_data->cancellable))
{
- search_thread_process_hits_idle (thread_data, queue_data->hits);
- g_list_free_full (queue_data->hits, g_object_unref);
- g_free (queue_data);
+ g_mutex_unlock (&thread_data->idle_mutex);
- return is_last ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE;
- }
- else
- {
- search_thread_done_idle (thread_data);
- g_free (queue_data);
+ if (hits)
+ {
+ g_list_free_full (hits, g_object_unref);
+ }
+ search_thread_done (thread_data);
+
+ return G_SOURCE_REMOVE;
}
+
}
- else
+
+ g_mutex_unlock (&thread_data->idle_mutex);
+
+ if (hits)
{
- g_mutex_unlock (&thread_data->idle_mutex);
+ search_thread_process_hits_idle (thread_data, hits);
+ g_list_free_full (hits, g_object_unref);
}
- return G_SOURCE_REMOVE;
+ return G_SOURCE_CONTINUE;
}
-/* 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)
+finish_search_thread (SearchThreadData *thread_data)
{
- gboolean idle_stopped;
- IdleQueueData *queue_data;
-
- g_assert (hits || clean_up);
-
g_mutex_lock (&thread_data->idle_mutex);
- idle_stopped = g_queue_is_empty (thread_data->idle_queue);
- if (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);
- }
+ thread_data->finished = TRUE;
g_mutex_unlock (&thread_data->idle_mutex);
- if (idle_stopped)
+ // If no results were processed, direclty finish the search, in the main
+ // thread.
+ if (thread_data->processing_id == 0)
{
- g_idle_add (search_thread_idle, thread_data);
+ g_idle_add (G_SOURCE_FUNC (search_thread_done), thread_data);
}
}
static void
-start_idle_processing (SearchThreadData *thread_data,
+process_batch_in_idle (SearchThreadData *thread_data,
GList *hits)
{
- start_idle_processing_or_cleanup (thread_data, hits, FALSE);
-}
+ g_return_if_fail (hits != NULL);
-static void
-start_idle_cleanup (SearchThreadData *thread_data)
-{
- start_idle_processing_or_cleanup (thread_data, NULL, TRUE);
+ g_mutex_lock (&thread_data->idle_mutex);
+ g_queue_push_tail (thread_data->idle_queue, hits);
+ g_mutex_unlock (&thread_data->idle_mutex);
+
+ if (thread_data->processing_id == 0)
+ {
+ thread_data->processing_id = g_idle_add (search_thread_process_idle, thread_data);
+ }
}
static void
-send_batch (SearchThreadData *thread_data)
+send_batch_in_idle (SearchThreadData *thread_data)
{
thread_data->n_processed_files = 0;
if (thread_data->hits)
{
- start_idle_processing (thread_data, thread_data->hits);
+ process_batch_in_idle (thread_data, thread_data->hits);
}
thread_data->hits = NULL;
}
@@ -398,7 +391,7 @@ visit_directory (GFile *dir,
data->n_processed_files++;
if (data->n_processed_files > BATCH_SIZE)
{
- send_batch (data);
+ send_batch_in_idle (data);
}
if (recursive != NAUTILUS_QUERY_RECURSIVE_NEVER &&
@@ -468,10 +461,10 @@ search_thread_func (gpointer user_data)
if (!g_cancellable_is_cancelled (data->cancellable))
{
- send_batch (data);
+ send_batch_in_idle (data);
}
- start_idle_cleanup (data);
+ finish_search_thread (data);
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]