1/*
2 * QEMU I/O task
3 *
4 * Copyright (c) 2015 Red Hat, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21#ifndef QIO_TASK_H
22#define QIO_TASK_H
23
24#include "qom/object.h"
25
26typedef struct QIOTask QIOTask;
27
28typedef void (*QIOTaskFunc)(QIOTask *task,
29 gpointer opaque);
30
31typedef void (*QIOTaskWorker)(QIOTask *task,
32 gpointer opaque);
33
34/**
35 * QIOTask:
36 *
37 * The QIOTask object provides a simple mechanism for reporting
38 * success / failure of long running background operations.
39 *
40 * A object on which the operation is to be performed could have
41 * a public API which accepts a task callback:
42 *
43 * <example>
44 * <title>Task function signature</title>
45 * <programlisting>
46 * void myobject_operation(QMyObject *obj,
47 * QIOTaskFunc *func,
48 * gpointer opaque,
49 * GDestroyNotify notify);
50 * </programlisting>
51 * </example>
52 *
53 * The 'func' parameter is the callback to be invoked, and 'opaque'
54 * is data to pass to it. The optional 'notify' function is used
55 * to free 'opaque' when no longer needed.
56 *
57 * When the operation completes, the 'func' callback will be
58 * invoked, allowing the calling code to determine the result
59 * of the operation. An example QIOTaskFunc implementation may
60 * look like
61 *
62 * <example>
63 * <title>Task callback implementation</title>
64 * <programlisting>
65 * static void myobject_operation_notify(QIOTask *task,
66 * gpointer opaque)
67 * {
68 * Error *err = NULL;
69 * if (qio_task_propagate_error(task, &err)) {
70 * ...deal with the failure...
71 * error_free(err);
72 * } else {
73 * QMyObject *src = QMY_OBJECT(qio_task_get_source(task));
74 * ...deal with the completion...
75 * }
76 * }
77 * </programlisting>
78 * </example>
79 *
80 * Now, lets say the implementation of the method using the
81 * task wants to set a timer to run once a second checking
82 * for completion of some activity. It would do something
83 * like
84 *
85 * <example>
86 * <title>Task function implementation</title>
87 * <programlisting>
88 * void myobject_operation(QMyObject *obj,
89 * QIOTaskFunc *func,
90 * gpointer opaque,
91 * GDestroyNotify notify)
92 * {
93 * QIOTask *task;
94 *
95 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
96 *
97 * g_timeout_add_full(G_PRIORITY_DEFAULT,
98 * 1000,
99 * myobject_operation_timer,
100 * task,
101 * NULL);
102 * }
103 * </programlisting>
104 * </example>
105 *
106 * It could equally have setup a watch on a file descriptor or
107 * created a background thread, or something else entirely.
108 * Notice that the source object is passed to the task, and
109 * QIOTask will hold a reference on that. This ensure that
110 * the QMyObject instance cannot be garbage collected while
111 * the async task is still in progress.
112 *
113 * In this case, myobject_operation_timer will fire after
114 * 3 secs and do
115 *
116 * <example>
117 * <title>Task timer function</title>
118 * <programlisting>
119 * gboolean myobject_operation_timer(gpointer opaque)
120 * {
121 * QIOTask *task = QIO_TASK(opaque);
122 * Error *err;*
123 *
124 * ...check something important...
125 * if (err) {
126 * qio_task_set_error(task, err);
127 * qio_task_complete(task);
128 * return FALSE;
129 * } else if (...work is completed ...) {
130 * qio_task_complete(task);
131 * return FALSE;
132 * }
133 * ...carry on polling ...
134 * return TRUE;
135 * }
136 * </programlisting>
137 * </example>
138 *
139 * The 'qio_task_complete' call in this method will trigger
140 * the callback func 'myobject_operation_notify' shown
141 * earlier to deal with the results.
142 *
143 * Once this function returns false, object_unref will be called
144 * automatically on the task causing it to be released and the
145 * ref on QMyObject dropped too.
146 *
147 * The QIOTask module can also be used to perform operations
148 * in a background thread context, while still reporting the
149 * results in the main event thread. This allows code which
150 * cannot easily be rewritten to be asychronous (such as DNS
151 * lookups) to be easily run non-blocking. Reporting the
152 * results in the main thread context means that the caller
153 * typically does not need to be concerned about thread
154 * safety wrt the QEMU global mutex.
155 *
156 * For example, the socket_listen() method will block the caller
157 * while DNS lookups take place if given a name, instead of IP
158 * address. The C library often do not provide a practical async
159 * DNS API, so the to get non-blocking DNS lookups in a portable
160 * manner requires use of a thread. So achieve a non-blocking
161 * socket listen using QIOTask would require:
162 *
163 * <example>
164 * static void myobject_listen_worker(QIOTask *task,
165 * gpointer opaque)
166 * {
167 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
168 * SocketAddress *addr = opaque;
169 * Error *err = NULL;
170 *
171 * obj->fd = socket_listen(addr, &err);
172 *
173 qio_task_set_error(task, err);
174 * }
175 *
176 * void myobject_listen_async(QMyObject *obj,
177 * SocketAddress *addr,
178 * QIOTaskFunc *func,
179 * gpointer opaque,
180 * GDestroyNotify notify)
181 * {
182 * QIOTask *task;
183 * SocketAddress *addrCopy;
184 *
185 * addrCopy = QAPI_CLONE(SocketAddress, addr);
186 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
187 *
188 * qio_task_run_in_thread(task, myobject_listen_worker,
189 * addrCopy,
190 * qapi_free_SocketAddress);
191 * }
192 * </example>
193 *
194 * NB, The 'func' callback passed into myobject_listen_async
195 * will be invoked from the main event thread, despite the
196 * actual operation being performed in a different thread.
197 */
198
199/**
200 * qio_task_new:
201 * @source: the object on which the operation is invoked
202 * @func: the callback to invoke when the task completes
203 * @opaque: opaque data to pass to @func when invoked
204 * @destroy: optional callback to free @opaque
205 *
206 * Creates a new task struct to track completion of a
207 * background operation running on the object @source.
208 * When the operation completes or fails, the callback
209 * @func will be invoked. The callback can access the
210 * 'err' attribute in the task object to determine if
211 * the operation was successful or not.
212 *
213 * The returned task will be released when qio_task_complete()
214 * is invoked.
215 *
216 * Returns: the task struct
217 */
218QIOTask *qio_task_new(Object *source,
219 QIOTaskFunc func,
220 gpointer opaque,
221 GDestroyNotify destroy);
222
223/**
224 * qio_task_run_in_thread:
225 * @task: the task struct
226 * @worker: the function to invoke in a thread
227 * @opaque: opaque data to pass to @worker
228 * @destroy: function to free @opaque
229 * @context: the context to run the complete hook. If %NULL, the
230 * default context will be used.
231 *
232 * Run a task in a background thread. When @worker
233 * returns it will call qio_task_complete() in
234 * the thread that is running the main loop associated
235 * with @context.
236 */
237void qio_task_run_in_thread(QIOTask *task,
238 QIOTaskWorker worker,
239 gpointer opaque,
240 GDestroyNotify destroy,
241 GMainContext *context);
242
243
244/**
245 * qio_task_wait_thread:
246 * @task: the task struct
247 *
248 * Wait for completion of a task that was previously
249 * invoked using qio_task_run_in_thread. This MUST
250 * ONLY be invoked if the task has not already
251 * completed, since after the completion callback
252 * is invoked, @task will have been freed.
253 *
254 * To avoid racing with execution of the completion
255 * callback provided with qio_task_new, this method
256 * MUST ONLY be invoked from the thread that is
257 * running the main loop associated with @context
258 * parameter to qio_task_run_in_thread.
259 *
260 * When the thread has completed, the completion
261 * callback provided to qio_task_new will be invoked.
262 * When that callback returns @task will be freed,
263 * so @task must not be referenced after this
264 * method completes.
265 */
266void qio_task_wait_thread(QIOTask *task);
267
268
269/**
270 * qio_task_complete:
271 * @task: the task struct
272 *
273 * Invoke the completion callback for @task and
274 * then free its memory.
275 */
276void qio_task_complete(QIOTask *task);
277
278
279/**
280 * qio_task_set_error:
281 * @task: the task struct
282 * @err: pointer to the error, or NULL
283 *
284 * Associate an error with the task, which can later
285 * be retrieved with the qio_task_propagate_error()
286 * method. This method takes ownership of @err, so
287 * it is not valid to access it after this call
288 * completes. If @err is NULL this is a no-op. If
289 * this is call multiple times, only the first
290 * provided @err will be recorded, later ones will
291 * be discarded and freed.
292 */
293void qio_task_set_error(QIOTask *task,
294 Error *err);
295
296
297/**
298 * qio_task_propagate_error:
299 * @task: the task struct
300 * @errp: pointer to a NULL-initialized error object
301 *
302 * Propagate the error associated with @task
303 * into @errp.
304 *
305 * Returns: true if an error was propagated, false otherwise
306 */
307bool qio_task_propagate_error(QIOTask *task,
308 Error **errp);
309
310
311/**
312 * qio_task_set_result_pointer:
313 * @task: the task struct
314 * @result: pointer to the result data
315 *
316 * Associate an opaque result with the task,
317 * which can later be retrieved with the
318 * qio_task_get_result_pointer() method
319 *
320 */
321void qio_task_set_result_pointer(QIOTask *task,
322 gpointer result,
323 GDestroyNotify notify);
324
325
326/**
327 * qio_task_get_result_pointer:
328 * @task: the task struct
329 *
330 * Retrieve the opaque result data associated
331 * with the task, if any.
332 *
333 * Returns: the task result, or NULL
334 */
335gpointer qio_task_get_result_pointer(QIOTask *task);
336
337
338/**
339 * qio_task_get_source:
340 * @task: the task struct
341 *
342 * Get the source object associated with the background
343 * task. The caller does not own a reference on the
344 * returned Object, and so should call object_ref()
345 * if it wants to keep the object pointer outside the
346 * lifetime of the QIOTask object.
347 *
348 * Returns: the source object
349 */
350Object *qio_task_get_source(QIOTask *task);
351
352#endif /* QIO_TASK_H */
353