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 27 typedef struct QIOTask QIOTask; 28 29 typedef void (*QIOTaskFunc)(Object *source, 30 Error *err, 31 gpointer opaque); 32 33 typedef 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 */ 195 QIOTask *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 */ 213 void 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 successfully completed 223 * and free the memory for @task. 224 */ 225 void 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 */ 238 void 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 */ 253 Object *qio_task_get_source(QIOTask *task); 254 255 #endif /* QIO_TASK_H__ */ 256