qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

task.h (11125B)


      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 */