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 "qom/object.h" 25 26 typedef struct QIOTask QIOTask; 27 28 typedef void (*QIOTaskFunc)(QIOTask *task, 29 gpointer opaque); 30 31 typedef void (*QIOTaskWorker)(QIOTask *task, 32 gpointer opaque); 33 34 /** 35 * QIOTask: 36 * 37 * The QIOTask object provides a simple mechanism for reporting 38 * success / failure of long running background operations. 39 * 40 * A object on which the operation is to be performed could have 41 * a public API which accepts a task callback: 42 * 43 * <example> 44 * <title>Task function signature</title> 45 * <programlisting> 46 * void myobject_operation(QMyObject *obj, 47 * QIOTaskFunc *func, 48 * gpointer opaque, 49 * GDestroyNotify notify); 50 * </programlisting> 51 * </example> 52 * 53 * The 'func' parameter is the callback to be invoked, and 'opaque' 54 * is data to pass to it. The optional 'notify' function is used 55 * to free 'opaque' when no longer needed. 56 * 57 * When the operation completes, the 'func' callback will be 58 * invoked, allowing the calling code to determine the result 59 * of the operation. An example QIOTaskFunc implementation may 60 * look like 61 * 62 * <example> 63 * <title>Task callback implementation</title> 64 * <programlisting> 65 * static void myobject_operation_notify(QIOTask *task, 66 * gpointer opaque) 67 * { 68 * Error *err = NULL; 69 * if (qio_task_propagate_error(task, &err)) { 70 * ...deal with the failure... 71 * error_free(err); 72 * } else { 73 * QMyObject *src = QMY_OBJECT(qio_task_get_source(task)); 74 * ...deal with the completion... 75 * } 76 * } 77 * </programlisting> 78 * </example> 79 * 80 * Now, lets say the implementation of the method using the 81 * task wants to set a timer to run once a second checking 82 * for completion of some activity. It would do something 83 * like 84 * 85 * <example> 86 * <title>Task function implementation</title> 87 * <programlisting> 88 * void myobject_operation(QMyObject *obj, 89 * QIOTaskFunc *func, 90 * gpointer opaque, 91 * GDestroyNotify notify) 92 * { 93 * QIOTask *task; 94 * 95 * task = qio_task_new(OBJECT(obj), func, opaque, notify); 96 * 97 * g_timeout_add_full(G_PRIORITY_DEFAULT, 98 * 1000, 99 * myobject_operation_timer, 100 * task, 101 * NULL); 102 * } 103 * </programlisting> 104 * </example> 105 * 106 * It could equally have setup a watch on a file descriptor or 107 * created a background thread, or something else entirely. 108 * Notice that the source object is passed to the task, and 109 * QIOTask will hold a reference on that. This ensure that 110 * the QMyObject instance cannot be garbage collected while 111 * the async task is still in progress. 112 * 113 * In this case, myobject_operation_timer will fire after 114 * 3 secs and do 115 * 116 * <example> 117 * <title>Task timer function</title> 118 * <programlisting> 119 * gboolean myobject_operation_timer(gpointer opaque) 120 * { 121 * QIOTask *task = QIO_TASK(opaque); 122 * Error *err;* 123 * 124 * ...check something important... 125 * if (err) { 126 * qio_task_set_error(task, err); 127 * qio_task_complete(task); 128 * return FALSE; 129 * } else if (...work is completed ...) { 130 * qio_task_complete(task); 131 * return FALSE; 132 * } 133 * ...carry on polling ... 134 * return TRUE; 135 * } 136 * </programlisting> 137 * </example> 138 * 139 * The 'qio_task_complete' call in this method will trigger 140 * the callback func 'myobject_operation_notify' shown 141 * earlier to deal with the results. 142 * 143 * Once this function returns false, object_unref will be called 144 * automatically on the task causing it to be released and the 145 * ref on QMyObject dropped too. 146 * 147 * The QIOTask module can also be used to perform operations 148 * in a background thread context, while still reporting the 149 * results in the main event thread. This allows code which 150 * cannot easily be rewritten to be asychronous (such as DNS 151 * lookups) to be easily run non-blocking. Reporting the 152 * results in the main thread context means that the caller 153 * typically does not need to be concerned about thread 154 * safety wrt the QEMU global mutex. 155 * 156 * For example, the socket_listen() method will block the caller 157 * while DNS lookups take place if given a name, instead of IP 158 * address. The C library often do not provide a practical async 159 * DNS API, so the to get non-blocking DNS lookups in a portable 160 * manner requires use of a thread. So achieve a non-blocking 161 * socket listen using QIOTask would require: 162 * 163 * <example> 164 * static void myobject_listen_worker(QIOTask *task, 165 * gpointer opaque) 166 * { 167 * QMyObject obj = QMY_OBJECT(qio_task_get_source(task)); 168 * SocketAddress *addr = opaque; 169 * Error *err = NULL; 170 * 171 * obj->fd = socket_listen(addr, &err); 172 * 173 qio_task_set_error(task, err); 174 * } 175 * 176 * void myobject_listen_async(QMyObject *obj, 177 * SocketAddress *addr, 178 * QIOTaskFunc *func, 179 * gpointer opaque, 180 * GDestroyNotify notify) 181 * { 182 * QIOTask *task; 183 * SocketAddress *addrCopy; 184 * 185 * addrCopy = QAPI_CLONE(SocketAddress, addr); 186 * task = qio_task_new(OBJECT(obj), func, opaque, notify); 187 * 188 * qio_task_run_in_thread(task, myobject_listen_worker, 189 * addrCopy, 190 * qapi_free_SocketAddress); 191 * } 192 * </example> 193 * 194 * NB, The 'func' callback passed into myobject_listen_async 195 * will be invoked from the main event thread, despite the 196 * actual operation being performed in a different thread. 197 */ 198 199 /** 200 * qio_task_new: 201 * @source: the object on which the operation is invoked 202 * @func: the callback to invoke when the task completes 203 * @opaque: opaque data to pass to @func when invoked 204 * @destroy: optional callback to free @opaque 205 * 206 * Creates a new task struct to track completion of a 207 * background operation running on the object @source. 208 * When the operation completes or fails, the callback 209 * @func will be invoked. The callback can access the 210 * 'err' attribute in the task object to determine if 211 * the operation was successful or not. 212 * 213 * The returned task will be released when qio_task_complete() 214 * is invoked. 215 * 216 * Returns: the task struct 217 */ 218 QIOTask *qio_task_new(Object *source, 219 QIOTaskFunc func, 220 gpointer opaque, 221 GDestroyNotify destroy); 222 223 /** 224 * qio_task_run_in_thread: 225 * @task: the task struct 226 * @worker: the function to invoke in a thread 227 * @opaque: opaque data to pass to @worker 228 * @destroy: function to free @opaque 229 * @context: the context to run the complete hook. If %NULL, the 230 * default context will be used. 231 * 232 * Run a task in a background thread. When @worker 233 * returns it will call qio_task_complete() in 234 * the thread that is running the main loop associated 235 * with @context. 236 */ 237 void qio_task_run_in_thread(QIOTask *task, 238 QIOTaskWorker worker, 239 gpointer opaque, 240 GDestroyNotify destroy, 241 GMainContext *context); 242 243 244 /** 245 * qio_task_wait_thread: 246 * @task: the task struct 247 * 248 * Wait for completion of a task that was previously 249 * invoked using qio_task_run_in_thread. This MUST 250 * ONLY be invoked if the task has not already 251 * completed, since after the completion callback 252 * is invoked, @task will have been freed. 253 * 254 * To avoid racing with execution of the completion 255 * callback provided with qio_task_new, this method 256 * MUST ONLY be invoked from the thread that is 257 * running the main loop associated with @context 258 * parameter to qio_task_run_in_thread. 259 * 260 * When the thread has completed, the completion 261 * callback provided to qio_task_new will be invoked. 262 * When that callback returns @task will be freed, 263 * so @task must not be referenced after this 264 * method completes. 265 */ 266 void qio_task_wait_thread(QIOTask *task); 267 268 269 /** 270 * qio_task_complete: 271 * @task: the task struct 272 * 273 * Invoke the completion callback for @task and 274 * then free its memory. 275 */ 276 void qio_task_complete(QIOTask *task); 277 278 279 /** 280 * qio_task_set_error: 281 * @task: the task struct 282 * @err: pointer to the error, or NULL 283 * 284 * Associate an error with the task, which can later 285 * be retrieved with the qio_task_propagate_error() 286 * method. This method takes ownership of @err, so 287 * it is not valid to access it after this call 288 * completes. If @err is NULL this is a no-op. If 289 * this is call multiple times, only the first 290 * provided @err will be recorded, later ones will 291 * be discarded and freed. 292 */ 293 void qio_task_set_error(QIOTask *task, 294 Error *err); 295 296 297 /** 298 * qio_task_propagate_error: 299 * @task: the task struct 300 * @errp: pointer to a NULL-initialized error object 301 * 302 * Propagate the error associated with @task 303 * into @errp. 304 * 305 * Returns: true if an error was propagated, false otherwise 306 */ 307 bool qio_task_propagate_error(QIOTask *task, 308 Error **errp); 309 310 311 /** 312 * qio_task_set_result_pointer: 313 * @task: the task struct 314 * @result: pointer to the result data 315 * 316 * Associate an opaque result with the task, 317 * which can later be retrieved with the 318 * qio_task_get_result_pointer() method 319 * 320 */ 321 void qio_task_set_result_pointer(QIOTask *task, 322 gpointer result, 323 GDestroyNotify notify); 324 325 326 /** 327 * qio_task_get_result_pointer: 328 * @task: the task struct 329 * 330 * Retrieve the opaque result data associated 331 * with the task, if any. 332 * 333 * Returns: the task result, or NULL 334 */ 335 gpointer qio_task_get_result_pointer(QIOTask *task); 336 337 338 /** 339 * qio_task_get_source: 340 * @task: the task struct 341 * 342 * Get the source object associated with the background 343 * task. The caller does not own a reference on the 344 * returned Object, and so should call object_ref() 345 * if it wants to keep the object pointer outside the 346 * lifetime of the QIOTask object. 347 * 348 * Returns: the source object 349 */ 350 Object *qio_task_get_source(QIOTask *task); 351 352 #endif /* QIO_TASK_H */ 353