aboutsummaryrefslogtreecommitdiff
path: root/include/io/task.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/io/task.h')
-rw-r--r--include/io/task.h154
1 files changed, 111 insertions, 43 deletions
diff --git a/include/io/task.h b/include/io/task.h
index 42028cb424..6021f51336 100644
--- a/include/io/task.h
+++ b/include/io/task.h
@@ -26,13 +26,11 @@
typedef struct QIOTask QIOTask;
-typedef void (*QIOTaskFunc)(Object *source,
- Error *err,
+typedef void (*QIOTaskFunc)(QIOTask *task,
gpointer opaque);
-typedef int (*QIOTaskWorker)(QIOTask *task,
- Error **errp,
- gpointer opaque);
+typedef void (*QIOTaskWorker)(QIOTask *task,
+ gpointer opaque);
/**
* QIOTask:
@@ -44,12 +42,12 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
* a public API which accepts a task callback:
*
* <example>
- * <title>Task callback function signature</title>
+ * <title>Task function signature</title>
* <programlisting>
* void myobject_operation(QMyObject *obj,
* QIOTaskFunc *func,
* gpointer opaque,
- * GDestroyNotify *notify);
+ * GDestroyNotify notify);
* </programlisting>
* </example>
*
@@ -57,17 +55,41 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
* is data to pass to it. The optional 'notify' function is used
* to free 'opaque' when no longer needed.
*
- * Now, lets say the implementation of this method wants to set
- * a timer to run once a second checking for completion of some
- * activity. It would do something like
+ * When the operation completes, the 'func' callback will be
+ * invoked, allowing the calling code to determine the result
+ * of the operation. An example QIOTaskFunc implementation may
+ * look like
*
* <example>
- * <title>Task callback function implementation</title>
+ * <title>Task callback implementation</title>
+ * <programlisting>
+ * static void myobject_operation_notify(QIOTask *task,
+ * gpointer opaque)
+ * {
+ * Error *err = NULL;
+ * if (qio_task_propagate_error(task, &err)) {
+ * ...deal with the failure...
+ * error_free(err);
+ * } else {
+ * QMyObject *src = QMY_OBJECT(qio_task_get_source(task));
+ * ...deal with the completion...
+ * }
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * Now, lets say the implementation of the method using the
+ * task wants to set a timer to run once a second checking
+ * for completion of some activity. It would do something
+ * like
+ *
+ * <example>
+ * <title>Task function implementation</title>
* <programlisting>
* void myobject_operation(QMyObject *obj,
* QIOTaskFunc *func,
* gpointer opaque,
- * GDestroyNotify *notify)
+ * GDestroyNotify notify)
* {
* QIOTask *task;
*
@@ -102,8 +124,8 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
*
* ...check something important...
* if (err) {
- * qio_task_abort(task, err);
- * error_free(task);
+ * qio_task_set_error(task, err);
+ * qio_task_complete(task);
* return FALSE;
* } else if (...work is completed ...) {
* qio_task_complete(task);
@@ -115,6 +137,10 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
* </programlisting>
* </example>
*
+ * The 'qio_task_complete' call in this method will trigger
+ * the callback func 'myobject_operation_notify' shown
+ * earlier to deal with the results.
+ *
* Once this function returns false, object_unref will be called
* automatically on the task causing it to be released and the
* ref on QMyObject dropped too.
@@ -136,25 +162,23 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
* socket listen using QIOTask would require:
*
* <example>
- * static int myobject_listen_worker(QIOTask *task,
- * Error **errp,
- * gpointer opaque)
+ * static void myobject_listen_worker(QIOTask *task,
+ * gpointer opaque)
* {
* QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
* SocketAddress *addr = opaque;
+ * Error *err = NULL;
*
- * obj->fd = socket_listen(addr, errp);
- * if (obj->fd < 0) {
- * return -1;
- * }
- * return 0;
+ * obj->fd = socket_listen(addr, &err);
+ *
+ qio_task_set_error(task, err);
* }
*
* void myobject_listen_async(QMyObject *obj,
* SocketAddress *addr,
* QIOTaskFunc *func,
* gpointer opaque,
- * GDestroyNotify *notify)
+ * GDestroyNotify notify)
* {
* QIOTask *task;
* SocketAddress *addrCopy;
@@ -187,8 +211,8 @@ typedef int (*QIOTaskWorker)(QIOTask *task,
* 'err' attribute in the task object to determine if
* the operation was successful or not.
*
- * The returned task will be released when one of
- * qio_task_abort() or qio_task_complete() are invoked.
+ * The returned task will be released when qio_task_complete()
+ * is invoked.
*
* Returns: the task struct
*/
@@ -204,10 +228,8 @@ QIOTask *qio_task_new(Object *source,
* @opaque: opaque data to pass to @worker
* @destroy: function to free @opaque
*
- * Run a task in a background thread. If @worker
- * returns 0 it will call qio_task_complete() in
- * the main event thread context. If @worker
- * returns -1 it will call qio_task_abort() in
+ * Run a task in a background thread. When @worker
+ * returns it will call qio_task_complete() in
* the main event thread context.
*/
void qio_task_run_in_thread(QIOTask *task,
@@ -219,24 +241,69 @@ void qio_task_run_in_thread(QIOTask *task,
* qio_task_complete:
* @task: the task struct
*
- * Mark the operation as successfully completed
- * and free the memory for @task.
+ * Invoke the completion callback for @task and
+ * then free its memory.
*/
void qio_task_complete(QIOTask *task);
+
+/**
+ * qio_task_set_error:
+ * @task: the task struct
+ * @err: pointer to the error, or NULL
+ *
+ * Associate an error with the task, which can later
+ * be retrieved with the qio_task_propagate_error()
+ * method. This method takes ownership of @err, so
+ * it is not valid to access it after this call
+ * completes. If @err is NULL this is a no-op. If
+ * this is call multiple times, only the first
+ * provided @err will be recorded, later ones will
+ * be discarded and freed.
+ */
+void qio_task_set_error(QIOTask *task,
+ Error *err);
+
+
/**
- * qio_task_abort:
+ * qio_task_propagate_error:
* @task: the task struct
- * @err: the error to record for the operation
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Propagate the error associated with @task
+ * into @errp.
+ *
+ * Returns: true if an error was propagated, false otherwise
+ */
+bool qio_task_propagate_error(QIOTask *task,
+ Error **errp);
+
+
+/**
+ * qio_task_set_result_pointer:
+ * @task: the task struct
+ * @result: pointer to the result data
+ *
+ * Associate an opaque result with the task,
+ * which can later be retrieved with the
+ * qio_task_get_result_pointer() method
+ *
+ */
+void qio_task_set_result_pointer(QIOTask *task,
+ gpointer result,
+ GDestroyNotify notify);
+
+
+/**
+ * qio_task_get_result_pointer:
+ * @task: the task struct
+ *
+ * Retrieve the opaque result data associated
+ * with the task, if any.
*
- * Mark the operation as failed, with @err providing
- * details about the failure. The @err may be freed
- * afer the function returns, as the notification
- * callback is invoked synchronously. The @task will
- * be freed when this call completes.
+ * Returns: the task result, or NULL
*/
-void qio_task_abort(QIOTask *task,
- Error *err);
+gpointer qio_task_get_result_pointer(QIOTask *task);
/**
@@ -244,9 +311,10 @@ void qio_task_abort(QIOTask *task,
* @task: the task struct
*
* Get the source object associated with the background
- * task. This returns a new reference to the object,
- * which the caller must released with object_unref()
- * when no longer required.
+ * task. The caller does not own a reference on the
+ * returned Object, and so should call object_ref()
+ * if it wants to keep the object pointer outside the
+ * lifetime of the QIOTask object.
*
* Returns: the source object
*/