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