xref: /openbmc/qemu/include/io/task.h (revision 3710586c)
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 asychronous (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