blob: 2e69d8a47f2d1bcd40b2d71863af7135788c749d [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
21#ifndef QIO_TASK_H__
22#define QIO_TASK_H__
23
24#include "qemu-common.h"
Daniel P. Berrangeb02db2d2015-03-18 17:25:45 +000025#include "qom/object.h"
26
27typedef struct QIOTask QIOTask;
28
29typedef void (*QIOTaskFunc)(Object *source,
30 Error *err,
31 gpointer opaque);
32
33typedef int (*QIOTaskWorker)(QIOTask *task,
34 Error **errp,
35 gpointer opaque);
36
37/**
38 * QIOTask:
39 *
40 * The QIOTask object provides a simple mechanism for reporting
41 * success / failure of long running background operations.
42 *
43 * A object on which the operation is to be performed could have
44 * a public API which accepts a task callback:
45 *
46 * <example>
47 * <title>Task callback function signature</title>
48 * <programlisting>
49 * void myobject_operation(QMyObject *obj,
50 * QIOTaskFunc *func,
51 * gpointer opaque,
52 * GDestroyNotify *notify);
53 * </programlisting>
54 * </example>
55 *
56 * The 'func' parameter is the callback to be invoked, and 'opaque'
57 * is data to pass to it. The optional 'notify' function is used
58 * to free 'opaque' when no longer needed.
59 *
60 * Now, lets say the implementation of this method wants to set
61 * a timer to run once a second checking for completion of some
62 * activity. It would do something like
63 *
64 * <example>
65 * <title>Task callback function implementation</title>
66 * <programlisting>
67 * void myobject_operation(QMyObject *obj,
68 * QIOTaskFunc *func,
69 * gpointer opaque,
70 * GDestroyNotify *notify)
71 * {
72 * QIOTask *task;
73 *
74 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
75 *
76 * g_timeout_add_full(G_PRIORITY_DEFAULT,
77 * 1000,
78 * myobject_operation_timer,
79 * task,
80 * NULL);
81 * }
82 * </programlisting>
83 * </example>
84 *
85 * It could equally have setup a watch on a file descriptor or
86 * created a background thread, or something else entirely.
87 * Notice that the source object is passed to the task, and
88 * QIOTask will hold a reference on that. This ensure that
89 * the QMyObject instance cannot be garbage collected while
90 * the async task is still in progress.
91 *
92 * In this case, myobject_operation_timer will fire after
93 * 3 secs and do
94 *
95 * <example>
96 * <title>Task timer function</title>
97 * <programlisting>
98 * gboolean myobject_operation_timer(gpointer opaque)
99 * {
100 * QIOTask *task = QIO_TASK(opaque);
101 * Error *err;*
102 *
103 * ...check something important...
104 * if (err) {
105 * qio_task_abort(task, err);
106 * error_free(task);
107 * return FALSE;
108 * } else if (...work is completed ...) {
109 * qio_task_complete(task);
110 * return FALSE;
111 * }
112 * ...carry on polling ...
113 * return TRUE;
114 * }
115 * </programlisting>
116 * </example>
117 *
118 * Once this function returns false, object_unref will be called
119 * automatically on the task causing it to be released and the
120 * ref on QMyObject dropped too.
121 *
122 * The QIOTask module can also be used to perform operations
123 * in a background thread context, while still reporting the
124 * results in the main event thread. This allows code which
125 * cannot easily be rewritten to be asychronous (such as DNS
126 * lookups) to be easily run non-blocking. Reporting the
127 * results in the main thread context means that the caller
128 * typically does not need to be concerned about thread
129 * safety wrt the QEMU global mutex.
130 *
131 * For example, the socket_listen() method will block the caller
132 * while DNS lookups take place if given a name, instead of IP
133 * address. The C library often do not provide a practical async
134 * DNS API, so the to get non-blocking DNS lookups in a portable
135 * manner requires use of a thread. So achieve a non-blocking
136 * socket listen using QIOTask would require:
137 *
138 * <example>
139 * static int myobject_listen_worker(QIOTask *task,
140 * Error **errp,
141 * gpointer opaque)
142 * {
143 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task));
144 * SocketAddress *addr = opaque;
145 *
146 * obj->fd = socket_listen(addr, errp);
147 * if (obj->fd < 0) {
148 * return -1;
149 * }
150 * return 0;
151 * }
152 *
153 * void myobject_listen_async(QMyObject *obj,
154 * SocketAddress *addr,
155 * QIOTaskFunc *func,
156 * gpointer opaque,
157 * GDestroyNotify *notify)
158 * {
159 * QIOTask *task;
160 * SocketAddress *addrCopy;
161 *
162 * qapi_copy_SocketAddress(&addrCopy, addr);
163 * task = qio_task_new(OBJECT(obj), func, opaque, notify);
164 *
165 * qio_task_run_in_thread(task, myobject_listen_worker,
166 * addrCopy,
167 * qapi_free_SocketAddress);
168 * }
169 * </example>
170 *
171 * NB, The 'func' callback passed into myobject_listen_async
172 * will be invoked from the main event thread, despite the
173 * actual operation being performed in a different thread.
174 */
175
176/**
177 * qio_task_new:
178 * @source: the object on which the operation is invoked
179 * @func: the callback to invoke when the task completes
180 * @opaque: opaque data to pass to @func when invoked
181 * @destroy: optional callback to free @opaque
182 *
183 * Creates a new task struct to track completion of a
184 * background operation running on the object @source.
185 * When the operation completes or fails, the callback
186 * @func will be invoked. The callback can access the
187 * 'err' attribute in the task object to determine if
188 * the operation was successful or not.
189 *
190 * The returned task will be released when one of
191 * qio_task_abort() or qio_task_complete() are invoked.
192 *
193 * Returns: the task struct
194 */
195QIOTask *qio_task_new(Object *source,
196 QIOTaskFunc func,
197 gpointer opaque,
198 GDestroyNotify destroy);
199
200/**
201 * qio_task_run_in_thread:
202 * @task: the task struct
203 * @worker: the function to invoke in a thread
204 * @opaque: opaque data to pass to @worker
205 * @destroy: function to free @opaque
206 *
207 * Run a task in a background thread. If @worker
208 * returns 0 it will call qio_task_complete() in
209 * the main event thread context. If @worker
210 * returns -1 it will call qio_task_abort() in
211 * the main event thread context.
212 */
213void qio_task_run_in_thread(QIOTask *task,
214 QIOTaskWorker worker,
215 gpointer opaque,
216 GDestroyNotify destroy);
217
218/**
219 * qio_task_complete:
220 * @task: the task struct
221 *
222 * Mark the operation as succesfully completed
223 * and free the memory for @task.
224 */
225void qio_task_complete(QIOTask *task);
226
227/**
228 * qio_task_abort:
229 * @task: the task struct
230 * @err: the error to record for the operation
231 *
232 * Mark the operation as failed, with @err providing
233 * details about the failure. The @err may be freed
234 * afer the function returns, as the notification
235 * callback is invoked synchronously. The @task will
236 * be freed when this call completes.
237 */
238void qio_task_abort(QIOTask *task,
239 Error *err);
240
241
242/**
243 * qio_task_get_source:
244 * @task: the task struct
245 *
246 * Get the source object associated with the background
247 * task. This returns a new reference to the object,
248 * which the caller must released with object_unref()
249 * when no longer required.
250 *
251 * Returns: the source object
252 */
253Object *qio_task_get_source(QIOTask *task);
254
255#endif /* QIO_TASK_H__ */