1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gio.Task; 26 27 private import gio.AsyncResultIF; 28 private import gio.AsyncResultT; 29 private import gio.Cancellable; 30 private import glib.ConstructionException; 31 private import glib.ErrorG; 32 private import glib.GException; 33 private import glib.MainContext; 34 private import glib.Source; 35 private import glib.Str; 36 private import gobject.ObjectG; 37 private import gtkc.gio; 38 public import gtkc.giotypes; 39 40 41 /** 42 * A #GTask represents and manages a cancellable "task". 43 * 44 * ## Asynchronous operations 45 * 46 * The most common usage of #GTask is as a #GAsyncResult, to 47 * manage data during an asynchronous operation. You call 48 * g_task_new() in the "start" method, followed by 49 * g_task_set_task_data() and the like if you need to keep some 50 * additional data associated with the task, and then pass the 51 * task object around through your asynchronous operation. 52 * Eventually, you will call a method such as 53 * g_task_return_pointer() or g_task_return_error(), which will 54 * save the value you give it and then invoke the task's callback 55 * function (waiting until the next iteration of the main 56 * loop first, if necessary). The caller will pass the #GTask back 57 * to the operation's finish function (as a #GAsyncResult), and 58 * you can use g_task_propagate_pointer() or the like to extract 59 * the return value. 60 * 61 * Here is an example for using GTask as a GAsyncResult: 62 * |[<!-- language="C" --> 63 * typedef struct { 64 * CakeFrostingType frosting; 65 * char *message; 66 * } DecorationData; 67 * 68 * static void 69 * decoration_data_free (DecorationData *decoration) 70 * { 71 * g_free (decoration->message); 72 * g_slice_free (DecorationData, decoration); 73 * } 74 * 75 * static void 76 * baked_cb (Cake *cake, 77 * gpointer user_data) 78 * { 79 * GTask *task = user_data; 80 * DecorationData *decoration = g_task_get_task_data (task); 81 * GError *error = NULL; 82 * 83 * if (cake == NULL) 84 * { 85 * g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, 86 * "Go to the supermarket"); 87 * g_object_unref (task); 88 * return; 89 * } 90 * 91 * if (!cake_decorate (cake, decoration->frosting, decoration->message, &error)) 92 * { 93 * g_object_unref (cake); 94 * // g_task_return_error() takes ownership of error 95 * g_task_return_error (task, error); 96 * g_object_unref (task); 97 * return; 98 * } 99 * 100 * g_task_return_pointer (task, cake, g_object_unref); 101 * g_object_unref (task); 102 * } 103 * 104 * void 105 * baker_bake_cake_async (Baker *self, 106 * guint radius, 107 * CakeFlavor flavor, 108 * CakeFrostingType frosting, 109 * const char *message, 110 * GCancellable *cancellable, 111 * GAsyncReadyCallback callback, 112 * gpointer user_data) 113 * { 114 * GTask *task; 115 * DecorationData *decoration; 116 * Cake *cake; 117 * 118 * task = g_task_new (self, cancellable, callback, user_data); 119 * if (radius < 3) 120 * { 121 * g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_TOO_SMALL, 122 * "%ucm radius cakes are silly", 123 * radius); 124 * g_object_unref (task); 125 * return; 126 * } 127 * 128 * cake = _baker_get_cached_cake (self, radius, flavor, frosting, message); 129 * if (cake != NULL) 130 * { 131 * // _baker_get_cached_cake() returns a reffed cake 132 * g_task_return_pointer (task, cake, g_object_unref); 133 * g_object_unref (task); 134 * return; 135 * } 136 * 137 * decoration = g_slice_new (DecorationData); 138 * decoration->frosting = frosting; 139 * decoration->message = g_strdup (message); 140 * g_task_set_task_data (task, decoration, (GDestroyNotify) decoration_data_free); 141 * 142 * _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); 143 * } 144 * 145 * Cake * 146 * baker_bake_cake_finish (Baker *self, 147 * GAsyncResult *result, 148 * GError **error) 149 * { 150 * g_return_val_if_fail (g_task_is_valid (result, self), NULL); 151 * 152 * return g_task_propagate_pointer (G_TASK (result), error); 153 * } 154 * ]| 155 * 156 * ## Chained asynchronous operations 157 * 158 * #GTask also tries to simplify asynchronous operations that 159 * internally chain together several smaller asynchronous 160 * operations. g_task_get_cancellable(), g_task_get_context(), 161 * and g_task_get_priority() allow you to get back the task's 162 * #GCancellable, #GMainContext, and [I/O priority][io-priority] 163 * when starting a new subtask, so you don't have to keep track 164 * of them yourself. g_task_attach_source() simplifies the case 165 * of waiting for a source to fire (automatically using the correct 166 * #GMainContext and priority). 167 * 168 * Here is an example for chained asynchronous operations: 169 * |[<!-- language="C" --> 170 * typedef struct { 171 * Cake *cake; 172 * CakeFrostingType frosting; 173 * char *message; 174 * } BakingData; 175 * 176 * static void 177 * decoration_data_free (BakingData *bd) 178 * { 179 * if (bd->cake) 180 * g_object_unref (bd->cake); 181 * g_free (bd->message); 182 * g_slice_free (BakingData, bd); 183 * } 184 * 185 * static void 186 * decorated_cb (Cake *cake, 187 * GAsyncResult *result, 188 * gpointer user_data) 189 * { 190 * GTask *task = user_data; 191 * GError *error = NULL; 192 * 193 * if (!cake_decorate_finish (cake, result, &error)) 194 * { 195 * g_object_unref (cake); 196 * g_task_return_error (task, error); 197 * g_object_unref (task); 198 * return; 199 * } 200 * 201 * // baking_data_free() will drop its ref on the cake, so we have to 202 * // take another here to give to the caller. 203 * g_task_return_pointer (result, g_object_ref (cake), g_object_unref); 204 * g_object_unref (task); 205 * } 206 * 207 * static void 208 * decorator_ready (gpointer user_data) 209 * { 210 * GTask *task = user_data; 211 * BakingData *bd = g_task_get_task_data (task); 212 * 213 * cake_decorate_async (bd->cake, bd->frosting, bd->message, 214 * g_task_get_cancellable (task), 215 * decorated_cb, task); 216 * } 217 * 218 * static void 219 * baked_cb (Cake *cake, 220 * gpointer user_data) 221 * { 222 * GTask *task = user_data; 223 * BakingData *bd = g_task_get_task_data (task); 224 * GError *error = NULL; 225 * 226 * if (cake == NULL) 227 * { 228 * g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, 229 * "Go to the supermarket"); 230 * g_object_unref (task); 231 * return; 232 * } 233 * 234 * bd->cake = cake; 235 * 236 * // Bail out now if the user has already cancelled 237 * if (g_task_return_error_if_cancelled (task)) 238 * { 239 * g_object_unref (task); 240 * return; 241 * } 242 * 243 * if (cake_decorator_available (cake)) 244 * decorator_ready (task); 245 * else 246 * { 247 * GSource *source; 248 * 249 * source = cake_decorator_wait_source_new (cake); 250 * // Attach @source to @task's GMainContext and have it call 251 * // decorator_ready() when it is ready. 252 * g_task_attach_source (task, source, 253 * G_CALLBACK (decorator_ready)); 254 * g_source_unref (source); 255 * } 256 * } 257 * 258 * void 259 * baker_bake_cake_async (Baker *self, 260 * guint radius, 261 * CakeFlavor flavor, 262 * CakeFrostingType frosting, 263 * const char *message, 264 * gint priority, 265 * GCancellable *cancellable, 266 * GAsyncReadyCallback callback, 267 * gpointer user_data) 268 * { 269 * GTask *task; 270 * BakingData *bd; 271 * 272 * task = g_task_new (self, cancellable, callback, user_data); 273 * g_task_set_priority (task, priority); 274 * 275 * bd = g_slice_new0 (BakingData); 276 * bd->frosting = frosting; 277 * bd->message = g_strdup (message); 278 * g_task_set_task_data (task, bd, (GDestroyNotify) baking_data_free); 279 * 280 * _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); 281 * } 282 * 283 * Cake * 284 * baker_bake_cake_finish (Baker *self, 285 * GAsyncResult *result, 286 * GError **error) 287 * { 288 * g_return_val_if_fail (g_task_is_valid (result, self), NULL); 289 * 290 * return g_task_propagate_pointer (G_TASK (result), error); 291 * } 292 * ]| 293 * 294 * ## Asynchronous operations from synchronous ones 295 * 296 * You can use g_task_run_in_thread() to turn a synchronous 297 * operation into an asynchronous one, by running it in a thread 298 * which will then dispatch the result back to the caller's 299 * #GMainContext when it completes. 300 * 301 * Running a task in a thread: 302 * |[<!-- language="C" --> 303 * typedef struct { 304 * guint radius; 305 * CakeFlavor flavor; 306 * CakeFrostingType frosting; 307 * char *message; 308 * } CakeData; 309 * 310 * static void 311 * cake_data_free (CakeData *cake_data) 312 * { 313 * g_free (cake_data->message); 314 * g_slice_free (CakeData, cake_data); 315 * } 316 * 317 * static void 318 * bake_cake_thread (GTask *task, 319 * gpointer source_object, 320 * gpointer task_data, 321 * GCancellable *cancellable) 322 * { 323 * Baker *self = source_object; 324 * CakeData *cake_data = task_data; 325 * Cake *cake; 326 * GError *error = NULL; 327 * 328 * cake = bake_cake (baker, cake_data->radius, cake_data->flavor, 329 * cake_data->frosting, cake_data->message, 330 * cancellable, &error); 331 * if (cake) 332 * g_task_return_pointer (task, cake, g_object_unref); 333 * else 334 * g_task_return_error (task, error); 335 * } 336 * 337 * void 338 * baker_bake_cake_async (Baker *self, 339 * guint radius, 340 * CakeFlavor flavor, 341 * CakeFrostingType frosting, 342 * const char *message, 343 * GCancellable *cancellable, 344 * GAsyncReadyCallback callback, 345 * gpointer user_data) 346 * { 347 * CakeData *cake_data; 348 * GTask *task; 349 * 350 * cake_data = g_slice_new (CakeData); 351 * cake_data->radius = radius; 352 * cake_data->flavor = flavor; 353 * cake_data->frosting = frosting; 354 * cake_data->message = g_strdup (message); 355 * task = g_task_new (self, cancellable, callback, user_data); 356 * g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); 357 * g_task_run_in_thread (task, bake_cake_thread); 358 * g_object_unref (task); 359 * } 360 * 361 * Cake * 362 * baker_bake_cake_finish (Baker *self, 363 * GAsyncResult *result, 364 * GError **error) 365 * { 366 * g_return_val_if_fail (g_task_is_valid (result, self), NULL); 367 * 368 * return g_task_propagate_pointer (G_TASK (result), error); 369 * } 370 * ]| 371 * 372 * ## Adding cancellability to uncancellable tasks 373 * 374 * Finally, g_task_run_in_thread() and g_task_run_in_thread_sync() 375 * can be used to turn an uncancellable operation into a 376 * cancellable one. If you call g_task_set_return_on_cancel(), 377 * passing %TRUE, then if the task's #GCancellable is cancelled, 378 * it will return control back to the caller immediately, while 379 * allowing the task thread to continue running in the background 380 * (and simply discarding its result when it finally does finish). 381 * Provided that the task thread is careful about how it uses 382 * locks and other externally-visible resources, this allows you 383 * to make "GLib-friendly" asynchronous and cancellable 384 * synchronous variants of blocking APIs. 385 * 386 * Cancelling a task: 387 * |[<!-- language="C" --> 388 * static void 389 * bake_cake_thread (GTask *task, 390 * gpointer source_object, 391 * gpointer task_data, 392 * GCancellable *cancellable) 393 * { 394 * Baker *self = source_object; 395 * CakeData *cake_data = task_data; 396 * Cake *cake; 397 * GError *error = NULL; 398 * 399 * cake = bake_cake (baker, cake_data->radius, cake_data->flavor, 400 * cake_data->frosting, cake_data->message, 401 * &error); 402 * if (error) 403 * { 404 * g_task_return_error (task, error); 405 * return; 406 * } 407 * 408 * // If the task has already been cancelled, then we don't want to add 409 * // the cake to the cake cache. Likewise, we don't want to have the 410 * // task get cancelled in the middle of updating the cache. 411 * // g_task_set_return_on_cancel() will return %TRUE here if it managed 412 * // to disable return-on-cancel, or %FALSE if the task was cancelled 413 * // before it could. 414 * if (g_task_set_return_on_cancel (task, FALSE)) 415 * { 416 * // If the caller cancels at this point, their 417 * // GAsyncReadyCallback won't be invoked until we return, 418 * // so we don't have to worry that this code will run at 419 * // the same time as that code does. But if there were 420 * // other functions that might look at the cake cache, 421 * // then we'd probably need a GMutex here as well. 422 * baker_add_cake_to_cache (baker, cake); 423 * g_task_return_pointer (task, cake, g_object_unref); 424 * } 425 * } 426 * 427 * void 428 * baker_bake_cake_async (Baker *self, 429 * guint radius, 430 * CakeFlavor flavor, 431 * CakeFrostingType frosting, 432 * const char *message, 433 * GCancellable *cancellable, 434 * GAsyncReadyCallback callback, 435 * gpointer user_data) 436 * { 437 * CakeData *cake_data; 438 * GTask *task; 439 * 440 * cake_data = g_slice_new (CakeData); 441 * 442 * ... 443 * 444 * task = g_task_new (self, cancellable, callback, user_data); 445 * g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); 446 * g_task_set_return_on_cancel (task, TRUE); 447 * g_task_run_in_thread (task, bake_cake_thread); 448 * } 449 * 450 * Cake * 451 * baker_bake_cake_sync (Baker *self, 452 * guint radius, 453 * CakeFlavor flavor, 454 * CakeFrostingType frosting, 455 * const char *message, 456 * GCancellable *cancellable, 457 * GError **error) 458 * { 459 * CakeData *cake_data; 460 * GTask *task; 461 * Cake *cake; 462 * 463 * cake_data = g_slice_new (CakeData); 464 * 465 * ... 466 * 467 * task = g_task_new (self, cancellable, NULL, NULL); 468 * g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); 469 * g_task_set_return_on_cancel (task, TRUE); 470 * g_task_run_in_thread_sync (task, bake_cake_thread); 471 * 472 * cake = g_task_propagate_pointer (task, error); 473 * g_object_unref (task); 474 * return cake; 475 * } 476 * ]| 477 * 478 * ## Porting from GSimpleAsyncResult 479 * 480 * #GTask's API attempts to be simpler than #GSimpleAsyncResult's 481 * in several ways: 482 * - You can save task-specific data with g_task_set_task_data(), and 483 * retrieve it later with g_task_get_task_data(). This replaces the 484 * abuse of g_simple_async_result_set_op_res_gpointer() for the same 485 * purpose with #GSimpleAsyncResult. 486 * - In addition to the task data, #GTask also keeps track of the 487 * [priority][io-priority], #GCancellable, and 488 * #GMainContext associated with the task, so tasks that consist of 489 * a chain of simpler asynchronous operations will have easy access 490 * to those values when starting each sub-task. 491 * - g_task_return_error_if_cancelled() provides simplified 492 * handling for cancellation. In addition, cancellation 493 * overrides any other #GTask return value by default, like 494 * #GSimpleAsyncResult does when 495 * g_simple_async_result_set_check_cancellable() is called. 496 * (You can use g_task_set_check_cancellable() to turn off that 497 * behavior.) On the other hand, g_task_run_in_thread() 498 * guarantees that it will always run your 499 * `task_func`, even if the task's #GCancellable 500 * is already cancelled before the task gets a chance to run; 501 * you can start your `task_func` with a 502 * g_task_return_error_if_cancelled() check if you need the 503 * old behavior. 504 * - The "return" methods (eg, g_task_return_pointer()) 505 * automatically cause the task to be "completed" as well, and 506 * there is no need to worry about the "complete" vs "complete 507 * in idle" distinction. (#GTask automatically figures out 508 * whether the task's callback can be invoked directly, or 509 * if it needs to be sent to another #GMainContext, or delayed 510 * until the next iteration of the current #GMainContext.) 511 * - The "finish" functions for #GTask-based operations are generally 512 * much simpler than #GSimpleAsyncResult ones, normally consisting 513 * of only a single call to g_task_propagate_pointer() or the like. 514 * Since g_task_propagate_pointer() "steals" the return value from 515 * the #GTask, it is not necessary to juggle pointers around to 516 * prevent it from being freed twice. 517 * - With #GSimpleAsyncResult, it was common to call 518 * g_simple_async_result_propagate_error() from the 519 * `_finish()` wrapper function, and have 520 * virtual method implementations only deal with successful 521 * returns. This behavior is deprecated, because it makes it 522 * difficult for a subclass to chain to a parent class's async 523 * methods. Instead, the wrapper function should just be a 524 * simple wrapper, and the virtual method should call an 525 * appropriate `g_task_propagate_` function. 526 * Note that wrapper methods can now use 527 * g_async_result_legacy_propagate_error() to do old-style 528 * #GSimpleAsyncResult error-returning behavior, and 529 * g_async_result_is_tagged() to check if a result is tagged as 530 * having come from the `_async()` wrapper 531 * function (for "short-circuit" results, such as when passing 532 * 0 to g_input_stream_read_async()). 533 */ 534 public class Task : ObjectG, AsyncResultIF 535 { 536 /** the main Gtk struct */ 537 protected GTask* gTask; 538 539 /** Get the main Gtk struct */ 540 public GTask* getTaskStruct() 541 { 542 return gTask; 543 } 544 545 /** the main Gtk struct as a void* */ 546 protected override void* getStruct() 547 { 548 return cast(void*)gTask; 549 } 550 551 protected override void setStruct(GObject* obj) 552 { 553 gTask = cast(GTask*)obj; 554 super.setStruct(obj); 555 } 556 557 /** 558 * Sets our main struct and passes it to the parent class. 559 */ 560 public this (GTask* gTask, bool ownedRef = false) 561 { 562 this.gTask = gTask; 563 super(cast(GObject*)gTask, ownedRef); 564 } 565 566 // add the AsyncResult capabilities 567 mixin AsyncResultT!(GTask); 568 569 /** 570 */ 571 572 public static GType getType() 573 { 574 return g_task_get_type(); 575 } 576 577 /** 578 * Creates a #GTask acting on @source_object, which will eventually be 579 * used to invoke @callback in the current 580 * [thread-default main context][g-main-context-push-thread-default]. 581 * 582 * Call this in the "start" method of your asynchronous method, and 583 * pass the #GTask around throughout the asynchronous operation. You 584 * can use g_task_set_task_data() to attach task-specific data to the 585 * object, which you can retrieve later via g_task_get_task_data(). 586 * 587 * By default, if @cancellable is cancelled, then the return value of 588 * the task will always be %G_IO_ERROR_CANCELLED, even if the task had 589 * already completed before the cancellation. This allows for 590 * simplified handling in cases where cancellation may imply that 591 * other objects that the task depends on have been destroyed. If you 592 * do not want this behavior, you can use 593 * g_task_set_check_cancellable() to change it. 594 * 595 * Params: 596 * sourceObject = the #GObject that owns 597 * this task, or %NULL. 598 * cancellable = optional #GCancellable object, %NULL to ignore. 599 * callback = a #GAsyncReadyCallback. 600 * callbackData = user data passed to @callback. 601 * 602 * Return: a #GTask. 603 * 604 * Since: 2.36 605 * 606 * Throws: ConstructionException GTK+ fails to create the object. 607 */ 608 public this(ObjectG sourceObject, Cancellable cancellable, GAsyncReadyCallback callback, void* callbackData) 609 { 610 auto p = g_task_new((sourceObject is null) ? null : sourceObject.getObjectGStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, callbackData); 611 612 if(p is null) 613 { 614 throw new ConstructionException("null returned by new"); 615 } 616 617 this(cast(GTask*) p, true); 618 } 619 620 /** 621 * Checks that @result is a #GTask, and that @source_object is its 622 * source object (or that @source_object is %NULL and @result has no 623 * source object). This can be used in g_return_if_fail() checks. 624 * 625 * Params: 626 * result = A #GAsyncResult 627 * sourceObject = the source object 628 * expected to be associated with the task 629 * 630 * Return: %TRUE if @result and @source_object are valid, %FALSE 631 * if not 632 * 633 * Since: 2.36 634 */ 635 public static bool isValid(AsyncResultIF result, ObjectG sourceObject) 636 { 637 return g_task_is_valid((result is null) ? null : result.getAsyncResultStruct(), (sourceObject is null) ? null : sourceObject.getObjectGStruct()) != 0; 638 } 639 640 /** 641 * Creates a #GTask and then immediately calls g_task_return_error() 642 * on it. Use this in the wrapper function of an asynchronous method 643 * when you want to avoid even calling the virtual method. You can 644 * then use g_async_result_is_tagged() in the finish method wrapper to 645 * check if the result there is tagged as having been created by the 646 * wrapper method, and deal with it appropriately if so. 647 * 648 * See also g_task_report_new_error(). 649 * 650 * Params: 651 * sourceObject = the #GObject that owns 652 * this task, or %NULL. 653 * callback = a #GAsyncReadyCallback. 654 * callbackData = user data passed to @callback. 655 * sourceTag = an opaque pointer indicating the source of this task 656 * error = error to report 657 * 658 * Since: 2.36 659 */ 660 public static void reportError(ObjectG sourceObject, GAsyncReadyCallback callback, void* callbackData, void* sourceTag, ErrorG error) 661 { 662 g_task_report_error((sourceObject is null) ? null : sourceObject.getObjectGStruct(), callback, callbackData, sourceTag, (error is null) ? null : error.getErrorGStruct()); 663 } 664 665 /** 666 * A utility function for dealing with async operations where you need 667 * to wait for a #GSource to trigger. Attaches @source to @task's 668 * #GMainContext with @task's [priority][io-priority], and sets @source's 669 * callback to @callback, with @task as the callback's `user_data`. 670 * 671 * This takes a reference on @task until @source is destroyed. 672 * 673 * Params: 674 * source = the source to attach 675 * callback = the callback to invoke when @source triggers 676 * 677 * Since: 2.36 678 */ 679 public void attachSource(Source source, GSourceFunc callback) 680 { 681 g_task_attach_source(gTask, (source is null) ? null : source.getSourceStruct(), callback); 682 } 683 684 /** 685 * Gets @task's #GCancellable 686 * 687 * Return: @task's #GCancellable 688 * 689 * Since: 2.36 690 */ 691 public Cancellable getCancellable() 692 { 693 auto p = g_task_get_cancellable(gTask); 694 695 if(p is null) 696 { 697 return null; 698 } 699 700 return ObjectG.getDObject!(Cancellable)(cast(GCancellable*) p); 701 } 702 703 /** 704 * Gets @task's check-cancellable flag. See 705 * g_task_set_check_cancellable() for more details. 706 * 707 * Since: 2.36 708 */ 709 public bool getCheckCancellable() 710 { 711 return g_task_get_check_cancellable(gTask) != 0; 712 } 713 714 /** 715 * Gets the #GMainContext that @task will return its result in (that 716 * is, the context that was the 717 * [thread-default main context][g-main-context-push-thread-default] 718 * at the point when @task was created). 719 * 720 * This will always return a non-%NULL value, even if the task's 721 * context is the default #GMainContext. 722 * 723 * Return: @task's #GMainContext 724 * 725 * Since: 2.36 726 */ 727 public MainContext getContext() 728 { 729 auto p = g_task_get_context(gTask); 730 731 if(p is null) 732 { 733 return null; 734 } 735 736 return new MainContext(cast(GMainContext*) p); 737 } 738 739 /** 740 * Gets @task's priority 741 * 742 * Return: @task's priority 743 * 744 * Since: 2.36 745 */ 746 public int getPriority() 747 { 748 return g_task_get_priority(gTask); 749 } 750 751 /** 752 * Gets @task's return-on-cancel flag. See 753 * g_task_set_return_on_cancel() for more details. 754 * 755 * Since: 2.36 756 */ 757 public bool getReturnOnCancel() 758 { 759 return g_task_get_return_on_cancel(gTask) != 0; 760 } 761 762 /** 763 * Gets the source object from @task. Like 764 * g_async_result_get_source_object(), but does not ref the object. 765 * 766 * Return: @task's source object, or %NULL 767 * 768 * Since: 2.36 769 */ 770 public ObjectG getSourceObject() 771 { 772 auto p = g_task_get_source_object(gTask); 773 774 if(p is null) 775 { 776 return null; 777 } 778 779 return ObjectG.getDObject!(ObjectG)(cast(GObject*) p); 780 } 781 782 /** 783 * Gets @task's source tag. See g_task_set_source_tag(). 784 * 785 * Return: @task's source tag 786 * 787 * Since: 2.36 788 */ 789 public void* getSourceTag() 790 { 791 return g_task_get_source_tag(gTask); 792 } 793 794 /** 795 * Gets @task's `task_data`. 796 * 797 * Return: @task's `task_data`. 798 * 799 * Since: 2.36 800 */ 801 public void* getTaskData() 802 { 803 return g_task_get_task_data(gTask); 804 } 805 806 /** 807 * Tests if @task resulted in an error. 808 * 809 * Return: %TRUE if the task resulted in an error, %FALSE otherwise. 810 * 811 * Since: 2.36 812 */ 813 public bool hadError() 814 { 815 return g_task_had_error(gTask) != 0; 816 } 817 818 /** 819 * Gets the result of @task as a #gboolean. 820 * 821 * If the task resulted in an error, or was cancelled, then this will 822 * instead return %FALSE and set @error. 823 * 824 * Since this method transfers ownership of the return value (or 825 * error) to the caller, you may only call it once. 826 * 827 * Return: the task result, or %FALSE on error 828 * 829 * Since: 2.36 830 * 831 * Throws: GException on failure. 832 */ 833 public bool propagateBoolean() 834 { 835 GError* err = null; 836 837 auto p = g_task_propagate_boolean(gTask, &err) != 0; 838 839 if (err !is null) 840 { 841 throw new GException( new ErrorG(err) ); 842 } 843 844 return p; 845 } 846 847 /** 848 * Gets the result of @task as an integer (#gssize). 849 * 850 * If the task resulted in an error, or was cancelled, then this will 851 * instead return -1 and set @error. 852 * 853 * Since this method transfers ownership of the return value (or 854 * error) to the caller, you may only call it once. 855 * 856 * Return: the task result, or -1 on error 857 * 858 * Since: 2.36 859 * 860 * Throws: GException on failure. 861 */ 862 public ptrdiff_t propagateInt() 863 { 864 GError* err = null; 865 866 auto p = g_task_propagate_int(gTask, &err); 867 868 if (err !is null) 869 { 870 throw new GException( new ErrorG(err) ); 871 } 872 873 return p; 874 } 875 876 /** 877 * Gets the result of @task as a pointer, and transfers ownership 878 * of that value to the caller. 879 * 880 * If the task resulted in an error, or was cancelled, then this will 881 * instead return %NULL and set @error. 882 * 883 * Since this method transfers ownership of the return value (or 884 * error) to the caller, you may only call it once. 885 * 886 * Return: the task result, or %NULL on error 887 * 888 * Since: 2.36 889 * 890 * Throws: GException on failure. 891 */ 892 public void* propagatePointer() 893 { 894 GError* err = null; 895 896 auto p = g_task_propagate_pointer(gTask, &err); 897 898 if (err !is null) 899 { 900 throw new GException( new ErrorG(err) ); 901 } 902 903 return p; 904 } 905 906 /** 907 * Sets @task's result to @result and completes the task (see 908 * g_task_return_pointer() for more discussion of exactly what this 909 * means). 910 * 911 * Params: 912 * result = the #gboolean result of a task function. 913 * 914 * Since: 2.36 915 */ 916 public void returnBoolean(bool result) 917 { 918 g_task_return_boolean(gTask, result); 919 } 920 921 /** 922 * Sets @task's result to @error (which @task assumes ownership of) 923 * and completes the task (see g_task_return_pointer() for more 924 * discussion of exactly what this means). 925 * 926 * Note that since the task takes ownership of @error, and since the 927 * task may be completed before returning from g_task_return_error(), 928 * you cannot assume that @error is still valid after calling this. 929 * Call g_error_copy() on the error if you need to keep a local copy 930 * as well. 931 * 932 * See also g_task_return_new_error(). 933 * 934 * Params: 935 * error = the #GError result of a task function. 936 * 937 * Since: 2.36 938 */ 939 public void returnError(ErrorG error) 940 { 941 g_task_return_error(gTask, (error is null) ? null : error.getErrorGStruct()); 942 } 943 944 /** 945 * Checks if @task's #GCancellable has been cancelled, and if so, sets 946 * @task's error accordingly and completes the task (see 947 * g_task_return_pointer() for more discussion of exactly what this 948 * means). 949 * 950 * Return: %TRUE if @task has been cancelled, %FALSE if not 951 * 952 * Since: 2.36 953 */ 954 public bool returnErrorIfCancelled() 955 { 956 return g_task_return_error_if_cancelled(gTask) != 0; 957 } 958 959 /** 960 * Sets @task's result to @result and completes the task (see 961 * g_task_return_pointer() for more discussion of exactly what this 962 * means). 963 * 964 * Params: 965 * result = the integer (#gssize) result of a task function. 966 * 967 * Since: 2.36 968 */ 969 public void returnInt(ptrdiff_t result) 970 { 971 g_task_return_int(gTask, result); 972 } 973 974 /** 975 * Sets @task's result to @result and completes the task. If @result 976 * is not %NULL, then @result_destroy will be used to free @result if 977 * the caller does not take ownership of it with 978 * g_task_propagate_pointer(). 979 * 980 * "Completes the task" means that for an ordinary asynchronous task 981 * it will either invoke the task's callback, or else queue that 982 * callback to be invoked in the proper #GMainContext, or in the next 983 * iteration of the current #GMainContext. For a task run via 984 * g_task_run_in_thread() or g_task_run_in_thread_sync(), calling this 985 * method will save @result to be returned to the caller later, but 986 * the task will not actually be completed until the #GTaskThreadFunc 987 * exits. 988 * 989 * Note that since the task may be completed before returning from 990 * g_task_return_pointer(), you cannot assume that @result is still 991 * valid after calling this, unless you are still holding another 992 * reference on it. 993 * 994 * Params: 995 * result = the pointer result of a task 996 * function 997 * resultDestroy = a #GDestroyNotify function. 998 * 999 * Since: 2.36 1000 */ 1001 public void returnPointer(void* result, GDestroyNotify resultDestroy) 1002 { 1003 g_task_return_pointer(gTask, result, resultDestroy); 1004 } 1005 1006 /** 1007 * Runs @task_func in another thread. When @task_func returns, @task's 1008 * #GAsyncReadyCallback will be invoked in @task's #GMainContext. 1009 * 1010 * This takes a ref on @task until the task completes. 1011 * 1012 * See #GTaskThreadFunc for more details about how @task_func is handled. 1013 * 1014 * Params: 1015 * taskFunc = a #GTaskThreadFunc 1016 * 1017 * Since: 2.36 1018 */ 1019 public void runInThread(GTaskThreadFunc taskFunc) 1020 { 1021 g_task_run_in_thread(gTask, taskFunc); 1022 } 1023 1024 /** 1025 * Runs @task_func in another thread, and waits for it to return or be 1026 * cancelled. You can use g_task_propagate_pointer(), etc, afterward 1027 * to get the result of @task_func. 1028 * 1029 * See #GTaskThreadFunc for more details about how @task_func is handled. 1030 * 1031 * Normally this is used with tasks created with a %NULL 1032 * `callback`, but note that even if the task does 1033 * have a callback, it will not be invoked when @task_func returns. 1034 * 1035 * Params: 1036 * taskFunc = a #GTaskThreadFunc 1037 * 1038 * Since: 2.36 1039 */ 1040 public void runInThreadSync(GTaskThreadFunc taskFunc) 1041 { 1042 g_task_run_in_thread_sync(gTask, taskFunc); 1043 } 1044 1045 /** 1046 * Sets or clears @task's check-cancellable flag. If this is %TRUE 1047 * (the default), then g_task_propagate_pointer(), etc, and 1048 * g_task_had_error() will check the task's #GCancellable first, and 1049 * if it has been cancelled, then they will consider the task to have 1050 * returned an "Operation was cancelled" error 1051 * (%G_IO_ERROR_CANCELLED), regardless of any other error or return 1052 * value the task may have had. 1053 * 1054 * If @check_cancellable is %FALSE, then the #GTask will not check the 1055 * cancellable itself, and it is up to @task's owner to do this (eg, 1056 * via g_task_return_error_if_cancelled()). 1057 * 1058 * If you are using g_task_set_return_on_cancel() as well, then 1059 * you must leave check-cancellable set %TRUE. 1060 * 1061 * Params: 1062 * checkCancellable = whether #GTask will check the state of 1063 * its #GCancellable for you. 1064 * 1065 * Since: 2.36 1066 */ 1067 public void setCheckCancellable(bool checkCancellable) 1068 { 1069 g_task_set_check_cancellable(gTask, checkCancellable); 1070 } 1071 1072 /** 1073 * Sets @task's priority. If you do not call this, it will default to 1074 * %G_PRIORITY_DEFAULT. 1075 * 1076 * This will affect the priority of #GSources created with 1077 * g_task_attach_source() and the scheduling of tasks run in threads, 1078 * and can also be explicitly retrieved later via 1079 * g_task_get_priority(). 1080 * 1081 * Params: 1082 * priority = the [priority][io-priority] of the request 1083 * 1084 * Since: 2.36 1085 */ 1086 public void setPriority(int priority) 1087 { 1088 g_task_set_priority(gTask, priority); 1089 } 1090 1091 /** 1092 * Sets or clears @task's return-on-cancel flag. This is only 1093 * meaningful for tasks run via g_task_run_in_thread() or 1094 * g_task_run_in_thread_sync(). 1095 * 1096 * If @return_on_cancel is %TRUE, then cancelling @task's 1097 * #GCancellable will immediately cause it to return, as though the 1098 * task's #GTaskThreadFunc had called 1099 * g_task_return_error_if_cancelled() and then returned. 1100 * 1101 * This allows you to create a cancellable wrapper around an 1102 * uninterruptable function. The #GTaskThreadFunc just needs to be 1103 * careful that it does not modify any externally-visible state after 1104 * it has been cancelled. To do that, the thread should call 1105 * g_task_set_return_on_cancel() again to (atomically) set 1106 * return-on-cancel %FALSE before making externally-visible changes; 1107 * if the task gets cancelled before the return-on-cancel flag could 1108 * be changed, g_task_set_return_on_cancel() will indicate this by 1109 * returning %FALSE. 1110 * 1111 * You can disable and re-enable this flag multiple times if you wish. 1112 * If the task's #GCancellable is cancelled while return-on-cancel is 1113 * %FALSE, then calling g_task_set_return_on_cancel() to set it %TRUE 1114 * again will cause the task to be cancelled at that point. 1115 * 1116 * If the task's #GCancellable is already cancelled before you call 1117 * g_task_run_in_thread()/g_task_run_in_thread_sync(), then the 1118 * #GTaskThreadFunc will still be run (for consistency), but the task 1119 * will also be completed right away. 1120 * 1121 * Params: 1122 * returnOnCancel = whether the task returns automatically when 1123 * it is cancelled. 1124 * 1125 * Return: %TRUE if @task's return-on-cancel flag was changed to 1126 * match @return_on_cancel. %FALSE if @task has already been 1127 * cancelled. 1128 * 1129 * Since: 2.36 1130 */ 1131 public bool setReturnOnCancel(bool returnOnCancel) 1132 { 1133 return g_task_set_return_on_cancel(gTask, returnOnCancel) != 0; 1134 } 1135 1136 /** 1137 * Sets @task's source tag. You can use this to tag a task return 1138 * value with a particular pointer (usually a pointer to the function 1139 * doing the tagging) and then later check it using 1140 * g_task_get_source_tag() (or g_async_result_is_tagged()) in the 1141 * task's "finish" function, to figure out if the response came from a 1142 * particular place. 1143 * 1144 * Params: 1145 * sourceTag = an opaque pointer indicating the source of this task 1146 * 1147 * Since: 2.36 1148 */ 1149 public void setSourceTag(void* sourceTag) 1150 { 1151 g_task_set_source_tag(gTask, sourceTag); 1152 } 1153 1154 /** 1155 * Sets @task's task data (freeing the existing task data, if any). 1156 * 1157 * Params: 1158 * taskData = task-specific data 1159 * taskDataDestroy = #GDestroyNotify for @task_data 1160 * 1161 * Since: 2.36 1162 */ 1163 public void setTaskData(void* taskData, GDestroyNotify taskDataDestroy) 1164 { 1165 g_task_set_task_data(gTask, taskData, taskDataDestroy); 1166 } 1167 }