Updated German translation.
[platform/upstream/glib.git] / gio / gsimpleasyncresult.c
index b3f62eb..d5c3e7b 100644 (file)
@@ -20,7 +20,7 @@
  * Author: Alexander Larsson <alexl@redhat.com>
  */
 
-#include <config.h>
+#include "config.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -32,6 +32,8 @@
 #endif
 
 #include "gsimpleasyncresult.h"
+#include "gasyncresult.h"
+#include "gcancellable.h"
 #include "gioscheduler.h"
 #include <gio/gioerror.h>
 #include "glibintl.h"
@@ -41,6 +43,7 @@
 /**
  * SECTION:gsimpleasyncresult
  * @short_description: Simple asynchronous results implementation
+ * @include: gio/gio.h
  * @see_also: #GAsyncResult
  *
  * Implements #GAsyncResult for simple cases. Most of the time, this 
  * Because of this, #GSimpleAsyncResult is used throughout GIO for 
  * handling asynchronous functions. 
  * 
- * GSimpleAsyncResult handles #GAsyncReadyCallback<!-- -->s, error reporting,
- * operation cancellation and the final state of an operation, completely
- * transparent to the application. Results can be returned as a pointer e.g. 
- * for functions that return data that is collected asynchronously,
- * a boolean value for checking the success or failure of an operation,
- * or a #gssize for operations which return the number of bytes modified 
- * by the operation; all of the simple return cases are covered.
+ * GSimpleAsyncResult handles #GAsyncReadyCallback<!-- -->s, error 
+ * reporting, operation cancellation and the final state of an operation, 
+ * completely transparent to the application. Results can be returned 
+ * as a pointer e.g. for functions that return data that is collected 
+ * asynchronously, a boolean value for checking the success or failure 
+ * of an operation, or a #gssize for operations which return the number 
+ * of bytes modified by the operation; all of the simple return cases 
+ * are covered.
  * 
  * Most of the time, an application will not need to know of the details 
- * of this API; it is handled transparently, and any necessary operations are 
- * handled by #GAsyncResult's interface. However, if implementing a new GIO 
- * module, for writing language bindings, or for complex applications that 
- * need better control of how asynchronous operations are completed, it i
- * important to understand this functionality.
+ * of this API; it is handled transparently, and any necessary operations 
+ * are handled by #GAsyncResult's interface. However, if implementing a 
+ * new GIO module, for writing language bindings, or for complex 
+ * applications that need better control of how asynchronous operation
+ * are completed, it is important to understand this functionality.
  * 
- * GSimpleAsyncResults are tagged with the calling function to ensure that 
- * asynchronous functions and their finishing functions are used together 
- * correctly.
+ * GSimpleAsyncResults are tagged with the calling function to ensure 
+ * that asynchronous functions and their finishing functions are used 
+ * together correctly.
  * 
  * To create a new #GSimpleAsyncResult, call g_simple_async_result_new(). 
  * If the result needs to be created for a #GError, use 
  * 
  * 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 Main Event Loop 
- * <!-- TODO: Crosslink -->, or it can use #GThread<!-- -->s if available. 
+ * GSimpleAsyncResult can integrate into GLib's event loop, #GMainLoop, 
+ * or it can use #GThread<!-- -->s if available. 
  * g_simple_async_result_complete() will finish an I/O task directly within 
  * the main event loop. g_simple_async_result_complete_in_idle() will 
  * integrate the I/O task into the main event loop as an idle function and 
@@ -153,9 +159,8 @@ g_simple_async_result_finalize (GObject *object)
 
   if (simple->error)
     g_error_free (simple->error);
-  
-  if (G_OBJECT_CLASS (g_simple_async_result_parent_class)->finalize)
-    (*G_OBJECT_CLASS (g_simple_async_result_parent_class)->finalize) (object);
+
+  G_OBJECT_CLASS (g_simple_async_result_parent_class)->finalize (object);
 }
 
 static void
@@ -174,7 +179,8 @@ g_simple_async_result_init (GSimpleAsyncResult *simple)
 
 /**
  * g_simple_async_result_new:
- * @source_object: a #GObject the asynchronous function was called with.
+ * @source_object: a #GObject the asynchronous function was called with,
+ * or %NULL.
  * @callback: a #GAsyncReadyCallback.
  * @user_data: user data passed to @callback.
  * @source_tag: the asynchronous function.
@@ -191,11 +197,14 @@ g_simple_async_result_new (GObject             *source_object,
 {
   GSimpleAsyncResult *simple;
 
-  g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
+  g_return_val_if_fail (!source_object || G_IS_OBJECT (source_object), NULL);
 
   simple = g_object_new (G_TYPE_SIMPLE_ASYNC_RESULT, NULL);
   simple->callback = callback;
-  simple->source_object = g_object_ref (source_object);
+  if (source_object)
+    simple->source_object = g_object_ref (source_object);
+  else
+    simple->source_object = NULL;
   simple->user_data = user_data;
   simple->source_tag = source_tag;
   
@@ -204,7 +213,7 @@ g_simple_async_result_new (GObject             *source_object,
 
 /**
  * g_simple_async_result_new_from_error:
- * @source_object: a #GObject.
+ * @source_object: a #GObject, or %NULL.
  * @callback: a #GAsyncReadyCallback.
  * @user_data: user data passed to @callback.
  * @error: a #GError location.
@@ -221,7 +230,7 @@ g_simple_async_result_new_from_error (GObject             *source_object,
 {
   GSimpleAsyncResult *simple;
 
-  g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
+  g_return_val_if_fail (!source_object || G_IS_OBJECT (source_object), NULL);
 
   simple = g_simple_async_result_new (source_object,
                                      callback,
@@ -233,7 +242,7 @@ g_simple_async_result_new_from_error (GObject             *source_object,
 
 /**
  * g_simple_async_result_new_error:
- * @source_object: a #GObject.
+ * @source_object: a #GObject, or %NULL.
  * @callback: a #GAsyncReadyCallback. 
  * @user_data: user data passed to @callback.
  * @domain: a #GQuark.
@@ -257,7 +266,7 @@ g_simple_async_result_new_error (GObject             *source_object,
   GSimpleAsyncResult *simple;
   va_list args;
   
-  g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
+  g_return_val_if_fail (!source_object || G_IS_OBJECT (source_object), NULL);
   g_return_val_if_fail (domain != 0, NULL);
   g_return_val_if_fail (format != NULL, NULL);
 
@@ -461,6 +470,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;
 }
@@ -504,6 +515,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;
 }
@@ -541,6 +554,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)
@@ -590,31 +606,65 @@ g_simple_async_result_complete_in_idle (GSimpleAsyncResult *simple)
 
 typedef struct {
   GSimpleAsyncResult *simple;
+  GCancellable *cancellable;
   GSimpleAsyncThreadFunc func;
 } RunInThreadData;
 
-static void
-run_in_thread (GIOJob       *job,
-               GCancellable *c,
-               gpointer      _data)
+
+static gboolean
+complete_in_idle_cb_for_thread (gpointer _data)
 {
   RunInThreadData *data = _data;
-  GSimpleAsyncResult *simple = data->simple;
+  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,
+               gpointer         _data)
+{
+  RunInThreadData *data = _data;
+  GSimpleAsyncResult *simple = data->simple;
+  GSource *source;
+  guint id;
+  
   if (simple->handle_cancellation &&
       g_cancellable_is_cancelled (c))
     g_simple_async_result_set_error (simple,
                                      G_IO_ERROR,
                                      G_IO_ERROR_CANCELLED,
-                                     _("Operation was cancelled"));
+                                     "%s", _("Operation was cancelled"));
   else
     data->func (simple,
                 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;
 }
 
 /**
@@ -640,7 +690,52 @@ g_simple_async_result_run_in_thread (GSimpleAsyncResult     *simple,
   data = g_new (RunInThreadData, 1);
   data->func = func;
   data->simple = g_object_ref (simple);
-  g_schedule_io_job (run_in_thread, data, NULL, io_priority, cancellable);
+  data->cancellable = cancellable;
+  if (cancellable)
+    g_object_ref (cancellable);
+  g_io_scheduler_push_job (run_in_thread, data, NULL, io_priority, cancellable);
+}
+
+/**
+ * g_simple_async_result_is_valid:
+ * @result: the #GAsyncResult passed to the _finish function.
+ * @source: the #GObject passed to the _finish function.
+ * @source_tag: the asynchronous function.
+ *
+ * Ensures that the data passed to the _finish function of an async
+ * operation is consistent.  Three checks are performed.
+ * 
+ * First, @result is checked to ensure that it is really a
+ * #GSimpleAsyncResult.  Second, @source is checked to ensure that it
+ * matches the source object of @result.  Third, @source_tag is
+ * checked to ensure that it is equal to the source_tag argument given
+ * to g_simple_async_result_new() (which, by convention, is a pointer
+ * to the _async function corresponding to the _finish function from
+ * which this function is called).
+ *
+ * Returns: #TRUE if all checks passed or #FALSE if any failed.
+ **/ 
+gboolean
+g_simple_async_result_is_valid (GAsyncResult *result,
+                                GObject      *source,
+                                gpointer      source_tag)
+{
+  GSimpleAsyncResult *simple;
+  GObject *cmp_source;
+
+  if (!G_IS_SIMPLE_ASYNC_RESULT (result))
+    return FALSE;
+  simple = (GSimpleAsyncResult *)result;
+
+  cmp_source = g_async_result_get_source_object (result);
+  if (cmp_source != source)
+    {
+      g_object_unref (cmp_source);
+      return FALSE;
+    }
+  g_object_unref (cmp_source);
+
+  return source_tag == g_simple_async_result_get_source_tag (simple);
 }
 
 /**
@@ -653,7 +748,9 @@ g_simple_async_result_run_in_thread (GSimpleAsyncResult     *simple,
  * @format: a formatted error reporting string.
  * @...: a list of variables to fill in @format.
  * 
- * Reports an error in an idle function.
+ * Reports an error in an asynchronous function in an idle function by 
+ * directly setting the contents of the #GAsyncResult with the given error
+ * information.
  **/
 void
 g_simple_async_report_error_in_idle (GObject             *object,
@@ -683,13 +780,15 @@ g_simple_async_report_error_in_idle (GObject             *object,
 }
 
 /**
- * g_simple_async_report_error_in_idle:
+ * g_simple_async_report_gerror_in_idle:
  * @object: a #GObject.
  * @callback: a #GAsyncReadyCallback. 
  * @user_data: user data passed to @callback.
  * @error: the #GError to report
  * 
- * Reports an error in an idle function.
+ * Reports an error in an idle function. Similar to 
+ * g_simple_async_report_error_in_idle(), but takes a #GError rather 
+ * than building a new one.
  **/
 void
 g_simple_async_report_gerror_in_idle (GObject *object,