blob: 9e09b95b2e8407fac90729b4babce6f939b172de [file] [log] [blame]
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +00001/*
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
Markus Armbruster2a6a4072016-06-29 13:47:03 +020021#ifndef QIO_TASK_H
22#define QIO_TASK_H
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000023
24#include "qemu-common.h"
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000025#include "qom/object.h"
26
27typedef struct QIOTask QIOTask;
28
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010029typedef void (*QIOTaskFunc)(QIOTask *task,
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000030 gpointer opaque);
31
Daniel P. Berrange59de5172016-08-11 17:38:07 +010032typedef void (*QIOTaskWorker)(QIOTask *task,
33 gpointer opaque);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000034
35/**
36 * QIOTask:
37 *
38 * The QIOTask object provides a simple mechanism for reporting
39 * success / failure of long running background operations.
40 *
41 * A object on which the operation is to be performed could have
42 * a public API which accepts a task callback:
43 *
44 * <example>
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010045 * <title>Task function signature</title>
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000046 * <programlisting>
47 * void myobject_operation(QMyObject *obj,
48 * QIOTaskFunc *func,
49 * gpointer opaque,
Daniel P. Berrangee8c8ade2016-08-11 14:25:30 +010050 * GDestroyNotify notify);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000051 * </programlisting>
52 * </example>
53 *
54 * The 'func' parameter is the callback to be invoked, and 'opaque'
55 * is data to pass to it. The optional 'notify' function is used
56 * to free 'opaque' when no longer needed.
57 *
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010058 * When the operation completes, the 'func' callback will be
59 * invoked, allowing the calling code to determine the result
60 * of the operation. An example QIOTaskFunc implementation may
61 * look like
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000062 *
63 * <example>
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010064 * <title>Task callback implementation</title>
65 * <programlisting>
66 * static void myobject_operation_notify(QIOTask *task,
67 * gpointer opaque)
68 * {
69 * Error *err = NULL;
70 * if (qio_task_propagate_error(task, &err)) {
71 * ...deal with the failure...
72 * error_free(err);
73 * } else {
74 * QMyObject *src = QMY_OBJECT(qio_task_get_source(task));
75 * ...deal with the completion...
76 * }
77 * }
78 * </programlisting>
79 * </example>
80 *
81 * Now, lets say the implementation of the method using the
82 * task wants to set a timer to run once a second checking
83 * for completion of some activity. It would do something
84 * like
85 *
86 * <example>
87 * <title>Task function implementation</title>
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000088 * <programlisting>
89 * void myobject_operation(QMyObject *obj,
90 * QIOTaskFunc *func,
91 * gpointer opaque,
Daniel P. Berrangee8c8ade2016-08-11 14:25:30 +010092 * GDestroyNotify notify)
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000093 * {
94 * QIOTask *task;
95 *
96 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
97 *
98 * g_timeout_add_full(G_PRIORITY_DEFAULT,
99 * 1000,
100 * myobject_operation_timer,
101 * task,
102 * NULL);
103 * }
104 * </programlisting>
105 * </example>
106 *
107 * It could equally have setup a watch on a file descriptor or
108 * created a background thread, or something else entirely.
109 * Notice that the source object is passed to the task, and
110 * QIOTask will hold a reference on that. This ensure that
111 * the QMyObject instance cannot be garbage collected while
112 * the async task is still in progress.
113 *
114 * In this case, myobject_operation_timer will fire after
115 * 3 secs and do
116 *
117 * <example>
118 * <title>Task timer function</title>
119 * <programlisting>
120 * gboolean myobject_operation_timer(gpointer opaque)
121 * {
122 * QIOTask *task = QIO_TASK(opaque);
123 * Error *err;*
124 *
125 * ...check something important...
126 * if (err) {
Daniel P. Berrange60e705c2016-08-11 15:20:58 +0100127 * qio_task_set_error(task, err);
128 * qio_task_complete(task);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000129 * return FALSE;
130 * } else if (...work is completed ...) {
131 * qio_task_complete(task);
132 * return FALSE;
133 * }
134 * ...carry on polling ...
135 * return TRUE;
136 * }
137 * </programlisting>
138 * </example>
139 *
Daniel P. Berrange60e705c2016-08-11 15:20:58 +0100140 * The 'qio_task_complete' call in this method will trigger
141 * the callback func 'myobject_operation_notify' shown
142 * earlier to deal with the results.
143 *
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000144 * Once this function returns false, object_unref will be called
145 * automatically on the task causing it to be released and the
146 * ref on QMyObject dropped too.
147 *
148 * The QIOTask module can also be used to perform operations
149 * in a background thread context, while still reporting the
150 * results in the main event thread. This allows code which
151 * cannot easily be rewritten to be asychronous (such as DNS
152 * lookups) to be easily run non-blocking. Reporting the
153 * results in the main thread context means that the caller
154 * typically does not need to be concerned about thread
155 * safety wrt the QEMU global mutex.
156 *
157 * For example, the socket_listen() method will block the caller
158 * while DNS lookups take place if given a name, instead of IP
159 * address. The C library often do not provide a practical async
160 * DNS API, so the to get non-blocking DNS lookups in a portable
161 * manner requires use of a thread. So achieve a non-blocking
162 * socket listen using QIOTask would require:
163 *
164 * <example>
Daniel P. Berrange59de5172016-08-11 17:38:07 +0100165 * static void myobject_listen_worker(QIOTask *task,
166 * gpointer opaque)
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000167 * {
168 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
169 * SocketAddress *addr = opaque;
Daniel P. Berrange59de5172016-08-11 17:38:07 +0100170 * Error *err = NULL;
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000171 *
Daniel P. Berrange59de5172016-08-11 17:38:07 +0100172 * obj->fd = socket_listen(addr, &err);
173 *
174 qio_task_set_error(task, err);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000175 * }
176 *
177 * void myobject_listen_async(QMyObject *obj,
178 * SocketAddress *addr,
179 * QIOTaskFunc *func,
180 * gpointer opaque,
Daniel P. Berrangee8c8ade2016-08-11 14:25:30 +0100181 * GDestroyNotify notify)
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000182 * {
183 * QIOTask *task;
184 * SocketAddress *addrCopy;
185 *
Eric Blake37f9e0a2016-06-09 10:48:45 -0600186 * addrCopy = QAPI_CLONE(SocketAddress, addr);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000187 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
188 *
189 * qio_task_run_in_thread(task, myobject_listen_worker,
190 * addrCopy,
191 * qapi_free_SocketAddress);
192 * }
193 * </example>
194 *
195 * NB, The 'func' callback passed into myobject_listen_async
196 * will be invoked from the main event thread, despite the
197 * actual operation being performed in a different thread.
198 */
199
200/**
201 * qio_task_new:
202 * @source: the object on which the operation is invoked
203 * @func: the callback to invoke when the task completes
204 * @opaque: opaque data to pass to @func when invoked
205 * @destroy: optional callback to free @opaque
206 *
207 * Creates a new task struct to track completion of a
208 * background operation running on the object @source.
209 * When the operation completes or fails, the callback
210 * @func will be invoked. The callback can access the
211 * 'err' attribute in the task object to determine if
212 * the operation was successful or not.
213 *
Daniel P. Berrange60e705c2016-08-11 15:20:58 +0100214 * The returned task will be released when qio_task_complete()
215 * is invoked.
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000216 *
217 * Returns: the task struct
218 */
219QIOTask *qio_task_new(Object *source,
220 QIOTaskFunc func,
221 gpointer opaque,
222 GDestroyNotify destroy);
223
224/**
225 * qio_task_run_in_thread:
226 * @task: the task struct
227 * @worker: the function to invoke in a thread
228 * @opaque: opaque data to pass to @worker
229 * @destroy: function to free @opaque
Peter Xua17536c2018-03-05 14:43:22 +0800230 * @context: the context to run the complete hook. If %NULL, the
231 * default context will be used.
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000232 *
Daniel P. Berrange60e705c2016-08-11 15:20:58 +0100233 * Run a task in a background thread. When @worker
234 * returns it will call qio_task_complete() in
Peter Xua17536c2018-03-05 14:43:22 +0800235 * the event thread context that provided.
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000236 */
237void qio_task_run_in_thread(QIOTask *task,
238 QIOTaskWorker worker,
239 gpointer opaque,
Peter Xua17536c2018-03-05 14:43:22 +0800240 GDestroyNotify destroy,
241 GMainContext *context);
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000242
243/**
244 * qio_task_complete:
245 * @task: the task struct
246 *
Daniel P. Berrange60e705c2016-08-11 15:20:58 +0100247 * Invoke the completion callback for @task and
248 * then free its memory.
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000249 */
250void qio_task_complete(QIOTask *task);
251
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000252
253/**
Daniel P. Berrange1a447e42016-08-11 14:40:44 +0100254 * qio_task_set_error:
255 * @task: the task struct
256 * @err: pointer to the error, or NULL
257 *
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.
266 */
267void qio_task_set_error(QIOTask *task,
268 Error *err);
269
270
271/**
272 * qio_task_propagate_error:
273 * @task: the task struct
274 * @errp: pointer to a NULL-initialized error object
275 *
276 * Propagate the error associated with @task
277 * into @errp.
278 *
279 * Returns: true if an error was propagated, false otherwise
280 */
281bool qio_task_propagate_error(QIOTask *task,
282 Error **errp);
283
284
285/**
Daniel P. Berrange52dd99e2016-08-11 14:36:21 +0100286 * qio_task_set_result_pointer:
287 * @task: the task struct
288 * @result: pointer to the result data
289 *
290 * Associate an opaque result with the task,
291 * which can later be retrieved with the
292 * qio_task_get_result_pointer() method
293 *
294 */
295void qio_task_set_result_pointer(QIOTask *task,
296 gpointer result,
297 GDestroyNotify notify);
298
299
300/**
301 * qio_task_get_result_pointer:
302 * @task: the task struct
303 *
304 * Retrieve the opaque result data associated
305 * with the task, if any.
306 *
307 * Returns: the task result, or NULL
308 */
309gpointer qio_task_get_result_pointer(QIOTask *task);
310
311
312/**
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000313 * qio_task_get_source:
314 * @task: the task struct
315 *
316 * Get the source object associated with the background
Daniel P. Berrange937470b2016-08-11 18:11:04 +0100317 * 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.
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +0000321 *
322 * Returns: the source object
323 */
324Object *qio_task_get_source(QIOTask *task);
325
Markus Armbruster2a6a4072016-06-29 13:47:03 +0200326#endif /* QIO_TASK_H */