[nautilus] batch-rename-dialog: Simplify name conflicts check
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] batch-rename-dialog: Simplify name conflicts check
- Date: Sun, 17 Jan 2021 12:16:26 +0000 (UTC)
commit 72ebd7af89b532d58843361711be24516e85340e
Author: Sachin Daluja <30343-sachindaluja users noreply gitlab gnome org>
Date: Thu Jan 14 08:54:01 2021 -0500
batch-rename-dialog: Simplify name conflicts check
We were spawning a background thread for performing the name conflict
check. Since the logic and data used for checking name conflicts
is not thread-safe we were executing the actual conflict check function
in the main thread (via g_main_context_invoke()). That routine in turn
ended up scheduling the actual work to execute in the callback
on_directory_conflicts_ready() per distinct parent directory. Thus
almost all the computationally intensive work was done via multiple
layers of indirection in the main thread.
Modify file_names_list_has_duplicates_async() to simply schedule the
actual name check function to be called per distict parent directory.
As before, most of the computationally intensive work is still done in
the callback registered via nautilus_directory_call_when_ready().
This greatly simplifies the design of the name conflict check by
eliminating the need for thread-safe synchronization of access and
modification of data that is used in the check.
src/nautilus-batch-rename-dialog.c | 205 ++++++++-----------------------------
1 file changed, 41 insertions(+), 164 deletions(-)
---
diff --git a/src/nautilus-batch-rename-dialog.c b/src/nautilus-batch-rename-dialog.c
index dde67158e..3464045c3 100644
--- a/src/nautilus-batch-rename-dialog.c
+++ b/src/nautilus-batch-rename-dialog.c
@@ -90,8 +90,7 @@ struct _NautilusBatchRenameDialog
GList *duplicates;
GList *distinct_parent_directories;
- GCancellable *conflict_cancellable;
- gboolean checking_conflicts;
+ GList *directories_pending_conflict_check;
/* this hash table has information about the status
* of all tags: availability, if it's currently used
@@ -119,6 +118,7 @@ typedef struct
static void update_display_text (NautilusBatchRenameDialog *dialog);
+static void cancel_conflict_check (NautilusBatchRenameDialog *self);
G_DEFINE_TYPE (NautilusBatchRenameDialog, nautilus_batch_rename_dialog, GTK_TYPE_DIALOG);
@@ -667,7 +667,7 @@ prepare_batch_rename (NautilusBatchRenameDialog *dialog)
/* wait for checking conflicts to finish, to be sure that
* the rename can actually take place */
- if (dialog->checking_conflicts)
+ if (dialog->directories_pending_conflict_check != NULL)
{
dialog->rename_clicked = TRUE;
return;
@@ -693,12 +693,6 @@ prepare_batch_rename (NautilusBatchRenameDialog *dialog)
gtk_widget_hide (GTK_WIDGET (dialog));
begin_batch_rename (dialog, dialog->new_names);
- if (dialog->conflict_cancellable)
- {
- g_cancellable_cancel (dialog->conflict_cancellable);
- g_clear_object (&dialog->conflict_cancellable);
- }
-
gtk_widget_destroy (GTK_WIDGET (dialog));
}
@@ -713,10 +707,9 @@ batch_rename_dialog_on_response (NautilusBatchRenameDialog *dialog,
}
else
{
- if (dialog->conflict_cancellable)
+ if (dialog->directories_pending_conflict_check != NULL)
{
- g_cancellable_cancel (dialog->conflict_cancellable);
- g_clear_object (&dialog->conflict_cancellable);
+ cancel_conflict_check (dialog);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
@@ -1177,174 +1170,70 @@ check_conflict_for_files (NautilusBatchRenameDialog *dialog,
g_hash_table_destroy (names_conflicts_table);
}
-static gboolean
-file_names_list_has_duplicates_finish (NautilusBatchRenameDialog *self,
- GAsyncResult *res,
- GError **error)
-{
- g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
-
- return g_task_propagate_boolean (G_TASK (res), error);
-}
-
-static void
-on_file_names_list_has_duplicates (GObject *object,
- GAsyncResult *res,
- gpointer user_data)
-{
- NautilusBatchRenameDialog *self;
- GError *error = NULL;
- gboolean success;
-
- self = NAUTILUS_BATCH_RENAME_DIALOG (object);
- success = file_names_list_has_duplicates_finish (self, res, &error);
-
- if (!success)
- {
- g_clear_error (&error);
- return;
- }
-
- self->duplicates = g_list_reverse (self->duplicates);
- self->checking_conflicts = FALSE;
- update_listbox (self);
-}
-
-typedef struct
-{
- GList *directories;
- NautilusDirectory *current_directory;
- GMutex wait_ready_mutex;
- GCond wait_ready_condition;
- gboolean directory_conflicts_ready;
-} CheckConflictsData;
-
static void
on_directory_conflicts_ready (NautilusDirectory *conflict_directory,
GList *files,
gpointer callback_data)
{
NautilusBatchRenameDialog *self;
- GTask *task;
- CheckConflictsData *task_data;
- GCancellable *cancellable;
- task = G_TASK (callback_data);
- task_data = g_task_get_task_data (task);
- cancellable = g_task_get_cancellable (task);
- self = NAUTILUS_BATCH_RENAME_DIALOG (g_task_get_source_object (task));
- if (!g_cancellable_is_cancelled (cancellable))
- {
- check_conflict_for_files (self, conflict_directory, files);
- }
+ self = NAUTILUS_BATCH_RENAME_DIALOG (callback_data);
- g_mutex_lock (&task_data->wait_ready_mutex);
- task_data->directory_conflicts_ready = TRUE;
- g_cond_signal (&task_data->wait_ready_condition);
- g_mutex_unlock (&task_data->wait_ready_mutex);
-}
+ check_conflict_for_files (self, conflict_directory, files);
-static gboolean
-check_conflicts_on_main_thread (gpointer user_data)
-{
- GTask *task = (GTask *) user_data;
- CheckConflictsData *task_data = g_task_get_task_data (task);
-
- nautilus_directory_call_when_ready (task_data->current_directory,
- NAUTILUS_FILE_ATTRIBUTE_INFO,
- TRUE,
- on_directory_conflicts_ready,
- task);
- return FALSE;
-}
+ g_assert (g_list_find (self->directories_pending_conflict_check, conflict_directory) != NULL);
-static void
-file_names_list_has_duplicates_async_thread (GTask *task,
- gpointer object,
- gpointer data,
- GCancellable *cancellable)
-{
- NautilusBatchRenameDialog *self;
- CheckConflictsData *task_data;
- GList *l;
-
- self = g_task_get_source_object (task);
- task_data = g_task_get_task_data (task);
- self->duplicates = NULL;
+ self->directories_pending_conflict_check = g_list_remove (self->directories_pending_conflict_check,
conflict_directory);
- g_mutex_init (&task_data->wait_ready_mutex);
- g_cond_init (&task_data->wait_ready_condition);
+ nautilus_directory_unref (conflict_directory);
- /* check if this is the last call of the callback */
- for (l = self->distinct_parent_directories; l != NULL; l = l->next)
+ if (self->directories_pending_conflict_check == NULL)
{
- if (g_task_return_error_if_cancelled (task))
- {
- return;
- }
-
- g_mutex_lock (&task_data->wait_ready_mutex);
- task_data->directory_conflicts_ready = FALSE;
+ self->duplicates = g_list_reverse (self->duplicates);
-
- task_data->current_directory = l->data;
- /* NautilusDirectory and NautilusFile are not thread safe, we need to call
- * them on the main thread.
- */
- g_main_context_invoke (NULL, check_conflicts_on_main_thread, task);
-
- /* We need to block this thread until the call_when_ready call is done,
- * if not the GTask would finalize. */
- while (!task_data->directory_conflicts_ready)
- {
- g_cond_wait (&task_data->wait_ready_condition,
- &task_data->wait_ready_mutex);
- }
-
- g_mutex_unlock (&task_data->wait_ready_mutex);
+ update_listbox (self);
}
-
- g_task_return_boolean (task, TRUE);
}
static void
-destroy_conflicts_task_data (gpointer data)
+cancel_conflict_check (NautilusBatchRenameDialog *self)
{
- CheckConflictsData *task_data = data;
+ GList *l;
+ NautilusDirectory *directory;
- if (task_data->directories)
+ for (l = self->directories_pending_conflict_check; l != NULL; l = l->next)
{
- g_list_free (task_data->directories);
- }
+ directory = l->data;
- g_mutex_clear (&task_data->wait_ready_mutex);
- g_cond_clear (&task_data->wait_ready_condition);
+ nautilus_directory_cancel_callback (directory,
+ on_directory_conflicts_ready,
+ self);
+ }
- g_free (task_data);
+ g_clear_list (&self->directories_pending_conflict_check, g_object_unref);
}
static void
-file_names_list_has_duplicates_async (NautilusBatchRenameDialog *dialog,
- GAsyncReadyCallback callback,
- gpointer user_data)
+file_names_list_has_duplicates_async (NautilusBatchRenameDialog *self)
{
- g_autoptr (GTask) task = NULL;
- CheckConflictsData *task_data;
+ GList *l;
- if (dialog->checking_conflicts == TRUE)
+ if (self->directories_pending_conflict_check != NULL)
{
- g_cancellable_cancel (dialog->conflict_cancellable);
- g_clear_object (&dialog->conflict_cancellable);
+ cancel_conflict_check (self);
}
- dialog->conflict_cancellable = g_cancellable_new ();
-
- dialog->checking_conflicts = TRUE;
+ self->directories_pending_conflict_check = nautilus_directory_list_copy
(self->distinct_parent_directories);
+ self->duplicates = NULL;
- task = g_task_new (dialog, dialog->conflict_cancellable, callback, user_data);
- task_data = g_new0 (CheckConflictsData, 1);
- g_task_set_task_data (task, task_data, destroy_conflicts_task_data);
- g_task_run_in_thread (task, file_names_list_has_duplicates_async_thread);
+ for (l = self->distinct_parent_directories; l != NULL; l = l->next)
+ {
+ nautilus_directory_call_when_ready (l->data,
+ NAUTILUS_FILE_ATTRIBUTE_INFO,
+ TRUE,
+ on_directory_conflicts_ready,
+ self);
+ }
}
static gboolean
@@ -1486,12 +1375,6 @@ numbering_tag_is_some_added (NautilusBatchRenameDialog *self)
static void
update_display_text (NautilusBatchRenameDialog *dialog)
{
- if (dialog->conflict_cancellable != NULL)
- {
- g_cancellable_cancel (dialog->conflict_cancellable);
- g_clear_object (&dialog->conflict_cancellable);
- }
-
if(dialog->selection == NULL)
{
return;
@@ -1524,9 +1407,7 @@ update_display_text (NautilusBatchRenameDialog *dialog)
return;
}
- file_names_list_has_duplicates_async (dialog,
- on_file_names_list_has_duplicates,
- NULL);
+ file_names_list_has_duplicates_async (dialog);
}
static void
@@ -2034,10 +1915,9 @@ nautilus_batch_rename_dialog_finalize (GObject *object)
dialog = NAUTILUS_BATCH_RENAME_DIALOG (object);
- if (dialog->checking_conflicts)
+ if (dialog->directories_pending_conflict_check != NULL)
{
- g_cancellable_cancel (dialog->conflict_cancellable);
- g_clear_object (&dialog->conflict_cancellable);
+ cancel_conflict_check (dialog);
}
g_clear_object (&dialog->numbering_order_menu);
@@ -2268,13 +2148,10 @@ nautilus_batch_rename_dialog_init (NautilusBatchRenameDialog *self)
self->duplicates = NULL;
self->distinct_parent_directories = NULL;
+ self->directories_pending_conflict_check = NULL;
self->new_names = NULL;
-
- self->checking_conflicts = FALSE;
-
self->rename_clicked = FALSE;
-
self->tag_info_table = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]