diff options
Diffstat (limited to 'include/io/task.h')
-rw-r--r-- | include/io/task.h | 154 |
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 */ |