diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2012-04-30 10:15:24 -0400 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2012-04-30 10:17:24 -0400 |
commit | e098781b3ede80517ceea56daa7f5a8c1c95f2af (patch) | |
tree | 49f2f42ea65723c23a89d23e8e367ba0644c2801 /src/nautilus-bookmark-list.c | |
parent | ed9057711896dd71a6e1524b9fcf963b9adb24c0 (diff) | |
download | nautilus-e098781b3ede80517ceea56daa7f5a8c1c95f2af.tar.gz |
bookmark-list: make sure to avoid sync I/O while loading/saving
Last patch introduces sync I/O in the load and save paths; avoid that by
explicitly using separate threads for saving and loading, thanks to
g_simple_async_result_run_in_thread().
Diffstat (limited to 'src/nautilus-bookmark-list.c')
-rw-r--r-- | src/nautilus-bookmark-list.c | 243 |
1 files changed, 129 insertions, 114 deletions
diff --git a/src/nautilus-bookmark-list.c b/src/nautilus-bookmark-list.c index c66a417c4..07e5a0c7f 100644 --- a/src/nautilus-bookmark-list.c +++ b/src/nautilus-bookmark-list.c @@ -462,82 +462,142 @@ nautilus_bookmark_list_length (NautilusBookmarkList *bookmarks) } static void -load_file_finish (NautilusBookmarkList *bookmarks, - GObject *source, - GAsyncResult *res) +process_next_op (NautilusBookmarkList *bookmarks); + +static void +op_processed_cb (NautilusBookmarkList *self) { - GError *error = NULL; - gchar *contents = NULL; - - g_file_load_contents_finish (G_FILE (source), - res, &contents, NULL, NULL, &error); - - if (error == NULL) { - char **lines; - int i; - - lines = g_strsplit (contents, "\n", -1); - for (i = 0; lines[i]; i++) { - /* Ignore empty or invalid lines that cannot be parsed properly */ - if (lines[i][0] != '\0' && lines[i][0] != ' ') { - /* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */ - /* we must seperate the bookmark uri and the potential label */ - char *space, *label; - - label = NULL; - space = strchr (lines[i], ' '); - if (space) { - *space = '\0'; - label = g_strdup (space + 1); - } - insert_bookmark_internal (bookmarks, - new_bookmark_from_uri (lines[i], label), - -1); - - g_free (label); + g_queue_pop_tail (self->pending_ops); + + if (!g_queue_is_empty (self->pending_ops)) { + process_next_op (self); + } +} + +static void +load_callback (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source); + gchar *contents; + char **lines; + int i; + + contents = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); + + if (contents == NULL) { + return; + } + + lines = g_strsplit (contents, "\n", -1); + for (i = 0; lines[i]; i++) { + /* Ignore empty or invalid lines that cannot be parsed properly */ + if (lines[i][0] != '\0' && lines[i][0] != ' ') { + /* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */ + /* we must seperate the bookmark uri and the potential label */ + char *space, *label; + + label = NULL; + space = strchr (lines[i], ' '); + if (space) { + *space = '\0'; + label = g_strdup (space + 1); } - } - g_free (contents); - g_strfreev (lines); - g_signal_emit (bookmarks, signals[CHANGED], 0); - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { - g_warning ("Could not load bookmark file: %s\n", error->message); - g_error_free (error); + insert_bookmark_internal (self, new_bookmark_from_uri (lines[i], label), -1); + g_free (label); + } } + + g_signal_emit (self, signals[CHANGED], 0); + op_processed_cb (self); + + g_strfreev (lines); } static void -load_file_async (NautilusBookmarkList *self, - GAsyncReadyCallback callback) +load_io_thread (GSimpleAsyncResult *result, + GObject *object, + GCancellable *cancellable) { GFile *file; + gchar *contents; + GError *error = NULL; file = nautilus_bookmark_list_get_file (); if (!g_file_query_exists (file, NULL)) { file = nautilus_bookmark_list_get_legacy_file (); } + g_file_load_contents (file, NULL, &contents, NULL, NULL, &error); + + if (error != NULL) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { + g_warning ("Could not load bookmark file: %s\n", error->message); + } + g_error_free (error); + } else { + g_simple_async_result_set_op_res_gpointer (result, contents, g_free); + } +} + +static void +load_file_async (NautilusBookmarkList *self) +{ + GSimpleAsyncResult *result; + /* Wipe out old list. */ clear (self); - /* keep the bookmark list alive */ - g_object_ref (self); - g_file_load_contents_async (file, NULL, callback, self); + result = g_simple_async_result_new (G_OBJECT (self), + load_callback, NULL, NULL); + g_simple_async_result_run_in_thread (result, load_io_thread, + G_PRIORITY_DEFAULT, NULL); + g_object_unref (result); +} +static void +save_callback (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + NautilusBookmarkList *self = NAUTILUS_BOOKMARK_LIST (source); + GFile *file; + + /* re-enable bookmark file monitoring */ + file = nautilus_bookmark_list_get_file (); + self->monitor = g_file_monitor_file (file, 0, NULL, NULL); g_object_unref (file); + + g_file_monitor_set_rate_limit (self->monitor, 1000); + g_signal_connect (self->monitor, "changed", + G_CALLBACK (bookmark_monitor_changed_cb), self); + + op_processed_cb (self); } static void -save_file_finish (NautilusBookmarkList *bookmarks, - GObject *source, - GAsyncResult *res) +save_io_thread (GSimpleAsyncResult *result, + GObject *object, + GCancellable *cancellable) { + gchar *contents, *path; + GFile *parent, *file; GError *error = NULL; - GFile *file; - g_file_replace_contents_finish (G_FILE (source), - res, NULL, &error); + file = nautilus_bookmark_list_get_file (); + parent = g_file_get_parent (file); + path = g_file_get_path (parent); + g_mkdir_with_parents (path, 0700); + g_free (path); + g_object_unref (parent); + + contents = g_simple_async_result_get_op_res_gpointer (result); + g_file_replace_contents (file, + contents, strlen (contents), + NULL, FALSE, 0, NULL, + NULL, &error); if (error != NULL) { g_warning ("Unable to replace contents of the bookmarks file: %s", @@ -545,37 +605,26 @@ save_file_finish (NautilusBookmarkList *bookmarks, g_error_free (error); } - file = nautilus_bookmark_list_get_file (); - - /* re-enable bookmark file monitoring */ - bookmarks->monitor = g_file_monitor_file (file, 0, NULL, NULL); - g_file_monitor_set_rate_limit (bookmarks->monitor, 1000); - g_signal_connect (bookmarks->monitor, "changed", - G_CALLBACK (bookmark_monitor_changed_cb), bookmarks); - g_object_unref (file); } static void -save_file_async (NautilusBookmarkList *bookmarks, - GAsyncReadyCallback callback) +save_file_async (NautilusBookmarkList *self) { - GFile *file; - GList *l; + GSimpleAsyncResult *result; GString *bookmark_string; - GFile *parent; - char *path; + gchar *contents; + GList *l; + + bookmark_string = g_string_new (NULL); /* temporarily disable bookmark file monitoring when writing file */ - if (bookmarks->monitor != NULL) { - g_file_monitor_cancel (bookmarks->monitor); - bookmarks->monitor = NULL; + if (self->monitor != NULL) { + g_file_monitor_cancel (self->monitor); + self->monitor = NULL; } - file = nautilus_bookmark_list_get_file (); - bookmark_string = g_string_new (NULL); - - for (l = bookmarks->list; l; l = l->next) { + for (l = self->list; l; l = l->next) { NautilusBookmark *bookmark; bookmark = NAUTILUS_BOOKMARK (l->data); @@ -597,48 +646,14 @@ save_file_async (NautilusBookmarkList *bookmarks, } } - /* keep the bookmark list alive */ - g_object_ref (bookmarks); - - parent = g_file_get_parent (file); - path = g_file_get_path (parent); - g_mkdir_with_parents (path, 0700); - g_free (path); - g_object_unref (parent); - - g_file_replace_contents_async (file, bookmark_string->str, - bookmark_string->len, NULL, - FALSE, 0, NULL, callback, - bookmarks); - - g_object_unref (file); -} - -static void -process_next_op (NautilusBookmarkList *bookmarks); - -static void -op_processed_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - NautilusBookmarkList *self = user_data; - int op; - - op = GPOINTER_TO_INT (g_queue_pop_tail (self->pending_ops)); - - if (op == LOAD_JOB) { - load_file_finish (self, source, res); - } else { - save_file_finish (self, source, res); - } - - if (!g_queue_is_empty (self->pending_ops)) { - process_next_op (self); - } + result = g_simple_async_result_new (G_OBJECT (self), + save_callback, NULL, NULL); + contents = g_string_free (bookmark_string, FALSE); + g_simple_async_result_set_op_res_gpointer (result, contents, g_free); - /* release the reference acquired during the _async method */ - g_object_unref (self); + g_simple_async_result_run_in_thread (result, save_io_thread, + G_PRIORITY_DEFAULT, NULL); + g_object_unref (result); } static void @@ -649,9 +664,9 @@ process_next_op (NautilusBookmarkList *bookmarks) op = GPOINTER_TO_INT (g_queue_peek_tail (bookmarks->pending_ops)); if (op == LOAD_JOB) { - load_file_async (bookmarks, op_processed_cb); + load_file_async (bookmarks); } else { - save_file_async (bookmarks, op_processed_cb); + save_file_async (bookmarks); } } |