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 "qapi/error.h" 26 #include "qom/object.h" 27 28 typedef struct QIOTask QIOTask; 29 30 typedef void (*QIOTaskFunc)(Object *source, 31 Error *err, 32 gpointer opaque); 33 34 typedef int (*QIOTaskWorker)(QIOTask *task, 35 Error **errp, 36 gpointer opaque); 37 38 /** 39 * QIOTask: 40 * 41 * The QIOTask object provides a simple mechanism for reporting 42 * success / failure of long running background operations. 43 * 44 * A object on which the operation is to be performed could have 45 * a public API which accepts a task callback: 46 * 47 * <example> 48 * <title>Task callback function signature</title> 49 * <programlisting> 50 * void myobject_operation(QMyObject *obj, 51 * QIOTaskFunc *func, 52 * gpointer opaque, 53 * GDestroyNotify *notify); 54 * </programlisting> 55 * </example> 56 * 57 * The 'func' parameter is the callback to be invoked, and 'opaque' 58 * is data to pass to it. The optional 'notify' function is used 59 * to free 'opaque' when no longer needed. 60 * 61 * Now, lets say the implementation of this method wants to set 62 * a timer to run once a second checking for completion of some 63 * activity. It would do something like 64 * 65 * <example> 66 * <title>Task callback function implementation</title> 67 * <programlisting> 68 * void myobject_operation(QMyObject *obj, 69 * QIOTaskFunc *func, 70 * gpointer opaque, 71 * GDestroyNotify *notify) 72 * { 73 * QIOTask *task; 74 * 75 * task = qio_task_new(OBJECT(obj), func, opaque, notify); 76 * 77 * g_timeout_add_full(G_PRIORITY_DEFAULT, 78 * 1000, 79 * myobject_operation_timer, 80 * task, 81 * NULL); 82 * } 83 * </programlisting> 84 * </example> 85 * 86 * It could equally have setup a watch on a file descriptor or 87 * created a background thread, or something else entirely. 88 * Notice that the source object is passed to the task, and 89 * QIOTask will hold a reference on that. This ensure that 90 * the QMyObject instance cannot be garbage collected while 91 * the async task is still in progress. 92 * 93 * In this case, myobject_operation_timer will fire after 94 * 3 secs and do 95 * 96 * <example> 97 * <title>Task timer function</title> 98 * <programlisting> 99 * gboolean myobject_operation_timer(gpointer opaque) 100 * { 101 * QIOTask *task = QIO_TASK(opaque); 102 * Error *err;* 103 * 104 * ...check something important... 105 * if (err) { 106 * qio_task_abort(task, err); 107 * error_free(task); 108 * return FALSE; 109 * } else if (...work is completed ...) { 110 * qio_task_complete(task); 111 * return FALSE; 112 * } 113 * ...carry on polling ... 114 * return TRUE; 115 * } 116 * </programlisting> 117 * </example> 118 * 119 * Once this function returns false, object_unref will be called 120 * automatically on the task causing it to be released and the 121 * ref on QMyObject dropped too. 122 * 123 * The QIOTask module can also be used to perform operations 124 * in a background thread context, while still reporting the 125 * results in the main event thread. This allows code which 126 * cannot easily be rewritten to be asychronous (such as DNS 127 * lookups) to be easily run non-blocking. Reporting the 128 * results in the main thread context means that the caller 129 * typically does not need to be concerned about thread 130 * safety wrt the QEMU global mutex. 131 * 132 * For example, the socket_listen() method will block the caller 133 * while DNS lookups take place if given a name, instead of IP 134 * address. The C library often do not provide a practical async 135 * DNS API, so the to get non-blocking DNS lookups in a portable 136 * manner requires use of a thread. So achieve a non-blocking 137 * socket listen using QIOTask would require: 138 * 139 * <example> 140 * static int myobject_listen_worker(QIOTask *task, 141 * Error **errp, 142 * gpointer opaque) 143 * { 144 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task)); 145 * SocketAddress *addr = opaque; 146 * 147 * obj->fd = socket_listen(addr, errp); 148 * if (obj->fd < 0) { 149 * return -1; 150 * } 151 * return 0; 152 * } 153 * 154 * void myobject_listen_async(QMyObject *obj, 155 * SocketAddress *addr, 156 * QIOTaskFunc *func, 157 * gpointer opaque, 158 * GDestroyNotify *notify) 159 * { 160 * QIOTask *task; 161 * SocketAddress *addrCopy; 162 * 163 * qapi_copy_SocketAddress(&addrCopy, addr); 164 * task = qio_task_new(OBJECT(obj), func, opaque, notify); 165 * 166 * qio_task_run_in_thread(task, myobject_listen_worker, 167 * addrCopy, 168 * qapi_free_SocketAddress); 169 * } 170 * </example> 171 * 172 * NB, The 'func' callback passed into myobject_listen_async 173 * will be invoked from the main event thread, despite the 174 * actual operation being performed in a different thread. 175 */ 176 177 /** 178 * qio_task_new: 179 * @source: the object on which the operation is invoked 180 * @func: the callback to invoke when the task completes 181 * @opaque: opaque data to pass to @func when invoked 182 * @destroy: optional callback to free @opaque 183 * 184 * Creates a new task struct to track completion of a 185 * background operation running on the object @source. 186 * When the operation completes or fails, the callback 187 * @func will be invoked. The callback can access the 188 * 'err' attribute in the task object to determine if 189 * the operation was successful or not. 190 * 191 * The returned task will be released when one of 192 * qio_task_abort() or qio_task_complete() are invoked. 193 * 194 * Returns: the task struct 195 */ 196 QIOTask *qio_task_new(Object *source, 197 QIOTaskFunc func, 198 gpointer opaque, 199 GDestroyNotify destroy); 200 201 /** 202 * qio_task_run_in_thread: 203 * @task: the task struct 204 * @worker: the function to invoke in a thread 205 * @opaque: opaque data to pass to @worker 206 * @destroy: function to free @opaque 207 * 208 * Run a task in a background thread. If @worker 209 * returns 0 it will call qio_task_complete() in 210 * the main event thread context. If @worker 211 * returns -1 it will call qio_task_abort() in 212 * the main event thread context. 213 */ 214 void qio_task_run_in_thread(QIOTask *task, 215 QIOTaskWorker worker, 216 gpointer opaque, 217 GDestroyNotify destroy); 218 219 /** 220 * qio_task_complete: 221 * @task: the task struct 222 * 223 * Mark the operation as succesfully completed 224 * and free the memory for @task. 225 */ 226 void qio_task_complete(QIOTask *task); 227 228 /** 229 * qio_task_abort: 230 * @task: the task struct 231 * @err: the error to record for the operation 232 * 233 * Mark the operation as failed, with @err providing 234 * details about the failure. The @err may be freed 235 * afer the function returns, as the notification 236 * callback is invoked synchronously. The @task will 237 * be freed when this call completes. 238 */ 239 void qio_task_abort(QIOTask *task, 240 Error *err); 241 242 243 /** 244 * qio_task_get_source: 245 * @task: the task struct 246 * 247 * Get the source object associated with the background 248 * task. This returns a new reference to the object, 249 * which the caller must released with object_unref() 250 * when no longer required. 251 * 252 * Returns: the source object 253 */ 254 Object *qio_task_get_source(QIOTask *task); 255 256 #endif /* QIO_TASK_H__ */ 257