qemu/include/io/task.h
<<
>>
Prefs
   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 "qemu-common.h"
  25#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__ */
 256