diff options
author | Ondrej Holy <oholy@redhat.com> | 2016-06-13 11:57:13 +0200 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2017-06-14 14:45:40 +0200 |
commit | 2eae1086656ebfa1b8eb20019636043a5e151c97 (patch) | |
tree | 2e8de4c757c959b08f2d24c0443b8039e0f4622d /client | |
parent | 805bd41bc675e9f341d2d733d0aef99b766a28ab (diff) | |
download | gvfs-2eae1086656ebfa1b8eb20019636043a5e151c97.tar.gz |
client: Port GDaemonFileEnumerator to GTask
GSimpleAsyncResult is deprecated in favour of GTask and should be replaced.
"changed" signal is added in order to allow splitting _sync and _async code
paths to use GTask as user_data for _async functionality.
https://bugzilla.gnome.org/show_bug.cgi?id=747412
Diffstat (limited to 'client')
-rw-r--r-- | client/gdaemonfileenumerator.c | 190 |
1 files changed, 95 insertions, 95 deletions
diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c index d0563592..aa30ee24 100644 --- a/client/gdaemonfileenumerator.c +++ b/client/gdaemonfileenumerator.c @@ -58,7 +58,6 @@ struct _GDaemonFileEnumerator int async_requested_files; gulong cancelled_tag; guint timeout_tag; - GSimpleAsyncResult *async_res; GMainLoop *next_files_mainloop; GMainContext *next_files_context; GSource *next_files_sync_timeout_source; @@ -68,6 +67,15 @@ struct _GDaemonFileEnumerator MetaTree *metadata_tree; }; + +enum +{ + CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + G_DEFINE_TYPE (GDaemonFileEnumerator, g_daemon_file_enumerator, G_TYPE_FILE_ENUMERATOR) static GFileInfo * g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, @@ -93,7 +101,6 @@ static void g_daemon_file_enumerator_close_async (GFileEnumerator static gboolean g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator, GAsyncResult *result, GError **error); -static void trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok); static void @@ -166,6 +173,13 @@ g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass) enumerator_class->close_fn = g_daemon_file_enumerator_close; enumerator_class->close_async = g_daemon_file_enumerator_close_async; enumerator_class->close_finish = g_daemon_file_enumerator_close_finish; + + signals[CHANGED] = g_signal_new ("changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -180,7 +194,7 @@ next_files_sync_check (GDaemonFileEnumerator *enumerator) g_mutex_unlock (&enumerator->next_files_mutex); } -static gboolean +static void handle_done (GVfsDBusEnumerator *object, GDBusMethodInvocation *invocation, gpointer user_data) @@ -189,17 +203,15 @@ handle_done (GVfsDBusEnumerator *object, G_LOCK (infos); enumerator->done = TRUE; - if (enumerator->async_requested_files > 0) - trigger_async_done (enumerator, TRUE); next_files_sync_check (enumerator); G_UNLOCK (infos); + g_signal_emit (enumerator, signals[CHANGED], 0); + gvfs_dbus_enumerator_complete_done (object, invocation); - - return TRUE; } -static gboolean +static void handle_got_info (GVfsDBusEnumerator *object, GDBusMethodInvocation *invocation, GVariant *arg_infos, @@ -230,15 +242,12 @@ handle_got_info (GVfsDBusEnumerator *object, G_LOCK (infos); enumerator->infos = g_list_concat (enumerator->infos, infos); - if (enumerator->async_requested_files > 0 && - g_list_length (enumerator->infos) >= enumerator->async_requested_files) - trigger_async_done (enumerator, TRUE); next_files_sync_check (enumerator); G_UNLOCK (infos); + g_signal_emit (enumerator, signals[CHANGED], 0); + gvfs_dbus_enumerator_complete_got_info (object, invocation); - - return TRUE; } static void @@ -362,34 +371,45 @@ add_metadata (GFileInfo *info, g_free (path); } -static GCancellable * -simple_async_result_get_cancellable (GSimpleAsyncResult *res) +static gboolean +_g_task_return_pointer_idle_cb (GTask *task) { - return g_object_get_data (G_OBJECT (res), "file-enumerator-cancellable"); + gpointer result; + GDestroyNotify notify; + + result = g_object_get_data (G_OBJECT (task), "_g_task_return_pointer_idle_result"); + notify = g_object_get_data (G_OBJECT (task), "_g_task_return_pointer_idle_notify"); + g_task_return_pointer (task, result, notify); + + return FALSE; } static void -simple_async_result_set_cancellable (GSimpleAsyncResult *res, - GCancellable *cancellable) +_g_task_return_pointer_idle (GTask *task, gpointer result, GDestroyNotify notify) { - if (!cancellable) - return; + GSource *source; + + g_object_set_data (G_OBJECT (task), "_g_task_return_pointer_idle_result", result); + g_object_set_data (G_OBJECT (task), "_g_task_return_pointer_idle_notify", notify); - g_object_set_data_full (G_OBJECT (res), - "file-enumerator-cancellable", - g_object_ref (cancellable), - g_object_unref); + source = g_idle_source_new (); + g_source_set_priority (source, g_task_get_priority (task)); + g_source_set_callback (source, (GSourceFunc) _g_task_return_pointer_idle_cb, + g_object_ref (task), g_object_unref); + g_source_attach (source, g_task_get_context (task)); + g_source_unref (source); } /* Called with infos lock held */ static void -trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) +trigger_async_done (GTask *task, gboolean ok) { - GList *rest, *l; - + GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (g_task_get_source_object (task)); + GList *rest, *l = NULL; + if (daemon->cancelled_tag != 0) { - GCancellable *cancellable = simple_async_result_get_cancellable (daemon->async_res); + GCancellable *cancellable = g_task_get_cancellable (task); /* If ok, we're a normal callback on the main thread, ensure protection against a thread cancelling and @@ -432,14 +452,12 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) daemon->infos = rest; g_list_foreach (l, (GFunc)add_metadata, daemon); - - g_simple_async_result_set_op_res_gpointer (daemon->async_res, - l, - (GDestroyNotify)free_info_list); } - g_simple_async_result_complete_in_idle (daemon->async_res); - + /* Result has to be returned in idle in order to avoid deadlock */ + _g_task_return_pointer_idle (task, l, (GDestroyNotify) free_info_list); + + g_signal_handlers_disconnect_by_data (daemon, task); daemon->cancelled_tag = 0; if (daemon->timeout_tag != 0) @@ -447,9 +465,8 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok) daemon->timeout_tag = 0; daemon->async_requested_files = 0; - - g_object_unref (daemon->async_res); - daemon->async_res = NULL; + + g_object_unref (task); } char * @@ -544,25 +561,30 @@ g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator, } static void +async_changed (GTask *task) +{ + GDaemonFileEnumerator *enumerator = G_DAEMON_FILE_ENUMERATOR (g_task_get_source_object (task)); + + G_LOCK (infos); + if (enumerator->done || g_list_length (enumerator->infos) >= enumerator->async_requested_files) + trigger_async_done (task, TRUE); + G_UNLOCK (infos); +} + +static void async_cancelled (GCancellable *cancellable, - GDaemonFileEnumerator *daemon) + GTask *task) { - g_simple_async_result_set_error (daemon->async_res, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); G_LOCK (infos); - trigger_async_done (daemon, FALSE); + trigger_async_done (task, FALSE); G_UNLOCK (infos); } static gboolean -async_timeout (gpointer data) +async_timeout (GTask *task) { - GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data); - G_LOCK (infos); - trigger_async_done (daemon, TRUE); + trigger_async_done (task, TRUE); G_UNLOCK (infos); return FALSE; } @@ -576,6 +598,11 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator, gpointer user_data) { GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator); + GTask *task; + + task = g_task_new (enumerator, cancellable, callback, user_data); + g_task_set_source_tag (task, g_daemon_file_enumerator_next_files_async); + g_task_set_priority (task, io_priority); if (daemon->sync_connection != NULL) { @@ -585,34 +612,30 @@ g_daemon_file_enumerator_next_files_async (GFileEnumerator *enumerator, * We could possibly pump it ourselves in this case, but i'm not sure * how much sense this makes, so we don't for now. */ - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't do asynchronous next_files() on a file enumerator created synchronously"); + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, + "Can't do asynchronous next_files() on a file enumerator created synchronously"); + g_object_unref (task); return; } - + G_LOCK (infos); daemon->cancelled_tag = 0; daemon->timeout_tag = 0; daemon->async_requested_files = num_files; - daemon->async_res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, - g_daemon_file_enumerator_next_files_async); - simple_async_result_set_cancellable (daemon->async_res, cancellable); /* Maybe we already have enough info to fulfill the requeust already */ if (daemon->done || g_list_length (daemon->infos) >= daemon->async_requested_files) - trigger_async_done (daemon, TRUE); + trigger_async_done (task, TRUE); else { daemon->timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS, - async_timeout, daemon); + (GSourceFunc) async_timeout, task); if (cancellable) - daemon->cancelled_tag = - g_cancellable_connect (cancellable, (GCallback)async_cancelled, - daemon, NULL); + daemon->cancelled_tag = + g_cancellable_connect (cancellable, (GCallback) async_cancelled, task, NULL); + + g_signal_connect_swapped (daemon, "changed", G_CALLBACK (async_changed), task); } G_UNLOCK (infos); @@ -623,23 +646,10 @@ g_daemon_file_enumerator_next_files_finish (GFileEnumerator *enumerator, GAsyncResult *res, GError **error) { - GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res); - GCancellable *cancellable; - GList *l; - - cancellable = simple_async_result_get_cancellable (result); - if (g_cancellable_is_cancelled (cancellable)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - "%s", _("Operation was cancelled")); - return NULL; - } + g_return_val_if_fail (g_task_is_valid (res, enumerator), NULL); + g_return_val_if_fail (g_async_result_is_tagged (res, g_daemon_file_enumerator_next_files_async), NULL); - l = g_simple_async_result_get_op_res_gpointer (result); - g_list_foreach (l, (GFunc)g_object_ref, NULL); - return g_list_copy (l); + return g_task_propagate_pointer (G_TASK (res), error); } static gboolean @@ -662,13 +672,12 @@ g_daemon_file_enumerator_close_async (GFileEnumerator *enumerator, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; + GTask *task; - res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, - g_daemon_file_enumerator_close_async); - simple_async_result_set_cancellable (res, cancellable); - g_simple_async_result_complete_in_idle (res); - g_object_unref (res); + task = g_task_new (enumerator, cancellable, callback, user_data); + g_task_set_source_tag (task, g_daemon_file_enumerator_close_async); + g_task_return_boolean (task, TRUE); + g_object_unref (task); } static gboolean @@ -676,17 +685,8 @@ g_daemon_file_enumerator_close_finish (GFileEnumerator *enumerator, GAsyncResult *result, GError **error) { - GCancellable *cancellable; - - cancellable = simple_async_result_get_cancellable (G_SIMPLE_ASYNC_RESULT (result)); - if (g_cancellable_is_cancelled (cancellable)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_CANCELLED, - "%s", _("Operation was cancelled")); - return FALSE; - } + g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE); + g_return_val_if_fail (g_async_result_is_tagged (result, g_daemon_file_enumerator_close_async), FALSE); - return TRUE; + return g_task_propagate_boolean (G_TASK (result), error); } |