xref: /openbmc/qemu/include/io/task.h (revision 3cad405b)
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 
26 typedef struct QIOTask QIOTask;
27 
28 typedef void (*QIOTaskFunc)(QIOTask *task,
29                             gpointer opaque);
30 
31 typedef 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 = NULL;
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  */
218 QIOTask *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  */
237 void 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  */
266 void 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  */
276 void 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  */
293 void 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  */
307 bool 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  */
321 void 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  */
335 gpointer 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  */
350 Object *qio_task_get_source(QIOTask *task);
351 
352 #endif /* QIO_TASK_H */
353