Bug 562452 - Ensure we return G_IO_ERROR_CANCELLED if cancelling

2008-12-10  Alexander Larsson  <alexl@redhat.com>

	Bug 562452 - Ensure we return G_IO_ERROR_CANCELLED if cancelling
	g_simple_async_result_run_in_thread
	
        * gsimpleasyncresult.c:
	Make g_simple_async_result_run_in_thread check cancellation before
	calling out to the user in the callback. This means we guarantee
	reporting cancels of async operations from the main threads, which
	is probably more in line with what users expect.
	
	Note that there are still no such guarantees for cancelling sync
	operations or cancelling async operation from outside the main
	thread. Furthermore, the exact behaviour of async implementations
	not using run_in_thread may differ.



svn path=/trunk/; revision=7740
This commit is contained in:
Alexander Larsson 2008-12-10 13:25:59 +00:00 committed by Alexander Larsson
parent b7c11505f9
commit 3b4ad625b9
2 changed files with 65 additions and 5 deletions

View File

@ -1,3 +1,19 @@
2008-12-10 Alexander Larsson <alexl@redhat.com>
Bug 562452 - Ensure we return G_IO_ERROR_CANCELLED if cancelling
g_simple_async_result_run_in_thread
* gsimpleasyncresult.c:
Make g_simple_async_result_run_in_thread check cancellation before
calling out to the user in the callback. This means we guarantee
reporting cancels of async operations from the main threads, which
is probably more in line with what users expect.
Note that there are still no such guarantees for cancelling sync
operations or cancelling async operation from outside the main
thread. Furthermore, the exact behaviour of async implementations
not using run_in_thread may differ.
2008-12-09 Alexander Larsson <alexl@redhat.com>
Bug 515777 - incorrect date&time on copy

View File

@ -83,7 +83,9 @@
*
* An asynchronous operation can be made to ignore a cancellation event by
* calling g_simple_async_result_set_handle_cancellation() with a
* #GSimpleAsyncResult for the operation and %FALSE.
* #GSimpleAsyncResult for the operation and %FALSE. This is useful for
* operations that are dangerous to cancel, such as close (which would
* cause a leak if cancelled before being run).
*
* GSimpleAsyncResult can integrate into GLib's event loop, #GMainLoop,
* or it can use #GThread<!-- -->s if available.
@ -464,6 +466,8 @@ g_simple_async_result_set_from_error (GSimpleAsyncResult *simple,
g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
g_return_if_fail (error != NULL);
if (simple->error)
g_error_free (simple->error);
simple->error = g_error_copy (error);
simple->failed = TRUE;
}
@ -507,6 +511,8 @@ g_simple_async_result_set_error_va (GSimpleAsyncResult *simple,
g_return_if_fail (domain != 0);
g_return_if_fail (format != NULL);
if (simple->error)
g_error_free (simple->error);
simple->error = _g_error_new_valist (domain, code, format, args);
simple->failed = TRUE;
}
@ -544,6 +550,9 @@ g_simple_async_result_set_error (GSimpleAsyncResult *simple,
* @simple: a #GSimpleAsyncResult.
*
* Completes an asynchronous I/O job.
* Must be called in the main thread, as it invokes the callback that
* should be called in the main thread. If you are in a different thread
* use g_simple_async_result_complete_in_idle().
**/
void
g_simple_async_result_complete (GSimpleAsyncResult *simple)
@ -593,9 +602,36 @@ g_simple_async_result_complete_in_idle (GSimpleAsyncResult *simple)
typedef struct {
GSimpleAsyncResult *simple;
GCancellable *cancellable;
GSimpleAsyncThreadFunc func;
} RunInThreadData;
static gboolean
complete_in_idle_cb_for_thread (gpointer _data)
{
RunInThreadData *data = _data;
GSimpleAsyncResult *simple;
simple = data->simple;
if (simple->handle_cancellation &&
g_cancellable_is_cancelled (data->cancellable))
g_simple_async_result_set_error (simple,
G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"%s", _("Operation was cancelled"));
g_simple_async_result_complete (simple);
if (data->cancellable)
g_object_unref (data->cancellable);
g_object_unref (data->simple);
g_free (data);
return FALSE;
}
static gboolean
run_in_thread (GIOSchedulerJob *job,
GCancellable *c,
@ -603,6 +639,8 @@ run_in_thread (GIOSchedulerJob *job,
{
RunInThreadData *data = _data;
GSimpleAsyncResult *simple = data->simple;
GSource *source;
guint id;
if (simple->handle_cancellation &&
g_cancellable_is_cancelled (c))
@ -615,9 +653,12 @@ run_in_thread (GIOSchedulerJob *job,
simple->source_object,
c);
g_simple_async_result_complete_in_idle (data->simple);
g_object_unref (data->simple);
g_free (data);
source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_set_callback (source, complete_in_idle_cb_for_thread, data, NULL);
id = g_source_attach (source, NULL);
g_source_unref (source);
return FALSE;
}
@ -645,6 +686,9 @@ g_simple_async_result_run_in_thread (GSimpleAsyncResult *simple,
data = g_new (RunInThreadData, 1);
data->func = func;
data->simple = g_object_ref (simple);
data->cancellable = cancellable;
if (cancellable)
g_object_ref (cancellable);
g_io_scheduler_push_job (run_in_thread, data, NULL, io_priority, cancellable);
}