io: change the QIOTask callback signature
[qemu/ar7.git] / include / io / task.h
blobad90970491528dafb4c4efe856d1efaffc2ea920
1 /*
2 * QEMU I/O task
4 * Copyright (c) 2015 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #ifndef QIO_TASK_H
22 #define QIO_TASK_H
24 #include "qemu-common.h"
25 #include "qom/object.h"
27 typedef struct QIOTask QIOTask;
29 typedef void (*QIOTaskFunc)(QIOTask *task,
30 gpointer opaque);
32 typedef int (*QIOTaskWorker)(QIOTask *task,
33 Error **errp,
34 gpointer opaque);
36 /**
37 * QIOTask:
39 * The QIOTask object provides a simple mechanism for reporting
40 * success / failure of long running background operations.
42 * A object on which the operation is to be performed could have
43 * a public API which accepts a task callback:
45 * <example>
46 * <title>Task function signature</title>
47 * <programlisting>
48 * void myobject_operation(QMyObject *obj,
49 * QIOTaskFunc *func,
50 * gpointer opaque,
51 * GDestroyNotify notify);
52 * </programlisting>
53 * </example>
55 * The 'func' parameter is the callback to be invoked, and 'opaque'
56 * is data to pass to it. The optional 'notify' function is used
57 * to free 'opaque' when no longer needed.
59 * When the operation completes, the 'func' callback will be
60 * invoked, allowing the calling code to determine the result
61 * of the operation. An example QIOTaskFunc implementation may
62 * look like
64 * <example>
65 * <title>Task callback implementation</title>
66 * <programlisting>
67 * static void myobject_operation_notify(QIOTask *task,
68 * gpointer opaque)
69 * {
70 * Error *err = NULL;
71 * if (qio_task_propagate_error(task, &err)) {
72 * ...deal with the failure...
73 * error_free(err);
74 * } else {
75 * QMyObject *src = QMY_OBJECT(qio_task_get_source(task));
76 * ...deal with the completion...
77 * }
78 * }
79 * </programlisting>
80 * </example>
82 * Now, lets say the implementation of the method using the
83 * task wants to set a timer to run once a second checking
84 * for completion of some activity. It would do something
85 * like
87 * <example>
88 * <title>Task function implementation</title>
89 * <programlisting>
90 * void myobject_operation(QMyObject *obj,
91 * QIOTaskFunc *func,
92 * gpointer opaque,
93 * GDestroyNotify notify)
94 * {
95 * QIOTask *task;
97 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
99 * g_timeout_add_full(G_PRIORITY_DEFAULT,
100 * 1000,
101 * myobject_operation_timer,
102 * task,
103 * NULL);
105 * </programlisting>
106 * </example>
108 * It could equally have setup a watch on a file descriptor or
109 * created a background thread, or something else entirely.
110 * Notice that the source object is passed to the task, and
111 * QIOTask will hold a reference on that. This ensure that
112 * the QMyObject instance cannot be garbage collected while
113 * the async task is still in progress.
115 * In this case, myobject_operation_timer will fire after
116 * 3 secs and do
118 * <example>
119 * <title>Task timer function</title>
120 * <programlisting>
121 * gboolean myobject_operation_timer(gpointer opaque)
123 * QIOTask *task = QIO_TASK(opaque);
124 * Error *err;*
126 * ...check something important...
127 * if (err) {
128 * qio_task_set_error(task, err);
129 * qio_task_complete(task);
130 * return FALSE;
131 * } else if (...work is completed ...) {
132 * qio_task_complete(task);
133 * return FALSE;
135 * ...carry on polling ...
136 * return TRUE;
138 * </programlisting>
139 * </example>
141 * The 'qio_task_complete' call in this method will trigger
142 * the callback func 'myobject_operation_notify' shown
143 * earlier to deal with the results.
145 * Once this function returns false, object_unref will be called
146 * automatically on the task causing it to be released and the
147 * ref on QMyObject dropped too.
149 * The QIOTask module can also be used to perform operations
150 * in a background thread context, while still reporting the
151 * results in the main event thread. This allows code which
152 * cannot easily be rewritten to be asychronous (such as DNS
153 * lookups) to be easily run non-blocking. Reporting the
154 * results in the main thread context means that the caller
155 * typically does not need to be concerned about thread
156 * safety wrt the QEMU global mutex.
158 * For example, the socket_listen() method will block the caller
159 * while DNS lookups take place if given a name, instead of IP
160 * address. The C library often do not provide a practical async
161 * DNS API, so the to get non-blocking DNS lookups in a portable
162 * manner requires use of a thread. So achieve a non-blocking
163 * socket listen using QIOTask would require:
165 * <example>
166 * static int myobject_listen_worker(QIOTask *task,
167 * Error **errp,
168 * gpointer opaque)
170 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
171 * SocketAddress *addr = opaque;
173 * obj->fd = socket_listen(addr, errp);
174 * if (obj->fd < 0) {
175 * return -1;
177 * return 0;
180 * void myobject_listen_async(QMyObject *obj,
181 * SocketAddress *addr,
182 * QIOTaskFunc *func,
183 * gpointer opaque,
184 * GDestroyNotify notify)
186 * QIOTask *task;
187 * SocketAddress *addrCopy;
189 * addrCopy = QAPI_CLONE(SocketAddress, addr);
190 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
192 * qio_task_run_in_thread(task, myobject_listen_worker,
193 * addrCopy,
194 * qapi_free_SocketAddress);
196 * </example>
198 * NB, The 'func' callback passed into myobject_listen_async
199 * will be invoked from the main event thread, despite the
200 * actual operation being performed in a different thread.
204 * qio_task_new:
205 * @source: the object on which the operation is invoked
206 * @func: the callback to invoke when the task completes
207 * @opaque: opaque data to pass to @func when invoked
208 * @destroy: optional callback to free @opaque
210 * Creates a new task struct to track completion of a
211 * background operation running on the object @source.
212 * When the operation completes or fails, the callback
213 * @func will be invoked. The callback can access the
214 * 'err' attribute in the task object to determine if
215 * the operation was successful or not.
217 * The returned task will be released when qio_task_complete()
218 * is invoked.
220 * Returns: the task struct
222 QIOTask *qio_task_new(Object *source,
223 QIOTaskFunc func,
224 gpointer opaque,
225 GDestroyNotify destroy);
228 * qio_task_run_in_thread:
229 * @task: the task struct
230 * @worker: the function to invoke in a thread
231 * @opaque: opaque data to pass to @worker
232 * @destroy: function to free @opaque
234 * Run a task in a background thread. When @worker
235 * returns it will call qio_task_complete() in
236 * the main event thread context.
238 void qio_task_run_in_thread(QIOTask *task,
239 QIOTaskWorker worker,
240 gpointer opaque,
241 GDestroyNotify destroy);
244 * qio_task_complete:
245 * @task: the task struct
247 * Invoke the completion callback for @task and
248 * then free its memory.
250 void qio_task_complete(QIOTask *task);
254 * qio_task_set_error:
255 * @task: the task struct
256 * @err: pointer to the error, or NULL
258 * Associate an error with the task, which can later
259 * be retrieved with the qio_task_propagate_error()
260 * method. This method takes ownership of @err, so
261 * it is not valid to access it after this call
262 * completes. If @err is NULL this is a no-op. If
263 * this is call multiple times, only the first
264 * provided @err will be recorded, later ones will
265 * be discarded and freed.
267 void qio_task_set_error(QIOTask *task,
268 Error *err);
272 * qio_task_propagate_error:
273 * @task: the task struct
274 * @errp: pointer to a NULL-initialized error object
276 * Propagate the error associated with @task
277 * into @errp.
279 * Returns: true if an error was propagated, false otherwise
281 bool qio_task_propagate_error(QIOTask *task,
282 Error **errp);
286 * qio_task_set_result_pointer:
287 * @task: the task struct
288 * @result: pointer to the result data
290 * Associate an opaque result with the task,
291 * which can later be retrieved with the
292 * qio_task_get_result_pointer() method
295 void qio_task_set_result_pointer(QIOTask *task,
296 gpointer result,
297 GDestroyNotify notify);
301 * qio_task_get_result_pointer:
302 * @task: the task struct
304 * Retrieve the opaque result data associated
305 * with the task, if any.
307 * Returns: the task result, or NULL
309 gpointer qio_task_get_result_pointer(QIOTask *task);
313 * qio_task_get_source:
314 * @task: the task struct
316 * Get the source object associated with the background
317 * task. The caller does not own a reference on the
318 * returned Object, and so should call object_ref()
319 * if it wants to keep the object pointer outside the
320 * lifetime of the QIOTask object.
322 * Returns: the source object
324 Object *qio_task_get_source(QIOTask *task);
326 #endif /* QIO_TASK_H */