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 asynchronous (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 BQL. 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 */ 351