Coverage Report

Created: 2025-07-01 07:09

/src/glib/gio/gtask.c
Line
Count
Source (jump to first uncovered line)
1
/* GIO - GLib Input, Output and Streaming Library
2
 *
3
 * Copyright 2011-2018 Red Hat, Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library 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 GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "config.h"
20
#include "gio_trace.h"
21
22
#include "gtask.h"
23
24
#include "gasyncresult.h"
25
#include "gcancellable.h"
26
#include "glib-private.h"
27
#include "gtrace-private.h"
28
29
#include "glibintl.h"
30
31
#include <string.h>
32
33
/**
34
 * SECTION:gtask
35
 * @short_description: Cancellable synchronous or asynchronous task
36
 *     and result
37
 * @include: gio/gio.h
38
 * @see_also: #GAsyncResult
39
 *
40
 * A #GTask represents and manages a cancellable "task".
41
 *
42
 * ## Asynchronous operations
43
 *
44
 * The most common usage of #GTask is as a #GAsyncResult, to
45
 * manage data during an asynchronous operation. You call
46
 * g_task_new() in the "start" method, followed by
47
 * g_task_set_task_data() and the like if you need to keep some
48
 * additional data associated with the task, and then pass the
49
 * task object around through your asynchronous operation.
50
 * Eventually, you will call a method such as
51
 * g_task_return_pointer() or g_task_return_error(), which will
52
 * save the value you give it and then invoke the task's callback
53
 * function in the
54
 * [thread-default main context][g-main-context-push-thread-default]
55
 * where it was created (waiting until the next iteration of the main
56
 * loop first, if necessary). The caller will pass the #GTask back to
57
 * the operation's finish function (as a #GAsyncResult), and you can
58
 * use g_task_propagate_pointer() or the like to extract the
59
 * 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 (task, g_object_ref (cake), g_object_unref);
204
 *       g_object_unref (task);
205
 *     }
206
 *
207
 *     static gboolean
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
 *       return G_SOURCE_REMOVE;
218
 *     }
219
 *
220
 *     static void
221
 *     baked_cb (Cake     *cake,
222
 *               gpointer  user_data)
223
 *     {
224
 *       GTask *task = user_data;
225
 *       BakingData *bd = g_task_get_task_data (task);
226
 *       GError *error = NULL;
227
 *
228
 *       if (cake == NULL)
229
 *         {
230
 *           g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR,
231
 *                                    "Go to the supermarket");
232
 *           g_object_unref (task);
233
 *           return;
234
 *         }
235
 *
236
 *       bd->cake = cake;
237
 *
238
 *       // Bail out now if the user has already cancelled
239
 *       if (g_task_return_error_if_cancelled (task))
240
 *         {
241
 *           g_object_unref (task);
242
 *           return;
243
 *         }
244
 *
245
 *       if (cake_decorator_available (cake))
246
 *         decorator_ready (task);
247
 *       else
248
 *         {
249
 *           GSource *source;
250
 *
251
 *           source = cake_decorator_wait_source_new (cake);
252
 *           // Attach @source to @task's GMainContext and have it call
253
 *           // decorator_ready() when it is ready.
254
 *           g_task_attach_source (task, source, decorator_ready);
255
 *           g_source_unref (source);
256
 *         }
257
 *     }
258
 *
259
 *     void
260
 *     baker_bake_cake_async (Baker               *self,
261
 *                            guint                radius,
262
 *                            CakeFlavor           flavor,
263
 *                            CakeFrostingType     frosting,
264
 *                            const char          *message,
265
 *                            gint                 priority,
266
 *                            GCancellable        *cancellable,
267
 *                            GAsyncReadyCallback  callback,
268
 *                            gpointer             user_data)
269
 *     {
270
 *       GTask *task;
271
 *       BakingData *bd;
272
 *
273
 *       task = g_task_new (self, cancellable, callback, user_data);
274
 *       g_task_set_priority (task, priority);
275
 *
276
 *       bd = g_slice_new0 (BakingData);
277
 *       bd->frosting = frosting;
278
 *       bd->message = g_strdup (message);
279
 *       g_task_set_task_data (task, bd, (GDestroyNotify) baking_data_free);
280
 *
281
 *       _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task);
282
 *     }
283
 *
284
 *     Cake *
285
 *     baker_bake_cake_finish (Baker         *self,
286
 *                             GAsyncResult  *result,
287
 *                             GError       **error)
288
 *     {
289
 *       g_return_val_if_fail (g_task_is_valid (result, self), NULL);
290
 *
291
 *       return g_task_propagate_pointer (G_TASK (result), error);
292
 *     }
293
 * ]|
294
 *
295
 * ## Asynchronous operations from synchronous ones
296
 *
297
 * You can use g_task_run_in_thread() to turn a synchronous
298
 * operation into an asynchronous one, by running it in a thread.
299
 * When it completes, the result will be dispatched to the
300
 * [thread-default main context][g-main-context-push-thread-default]
301
 * where the #GTask was created.
302
 *
303
 * Running a task in a thread:
304
 *   |[<!-- language="C" -->
305
 *     typedef struct {
306
 *       guint radius;
307
 *       CakeFlavor flavor;
308
 *       CakeFrostingType frosting;
309
 *       char *message;
310
 *     } CakeData;
311
 *
312
 *     static void
313
 *     cake_data_free (CakeData *cake_data)
314
 *     {
315
 *       g_free (cake_data->message);
316
 *       g_slice_free (CakeData, cake_data);
317
 *     }
318
 *
319
 *     static void
320
 *     bake_cake_thread (GTask         *task,
321
 *                       gpointer       source_object,
322
 *                       gpointer       task_data,
323
 *                       GCancellable  *cancellable)
324
 *     {
325
 *       Baker *self = source_object;
326
 *       CakeData *cake_data = task_data;
327
 *       Cake *cake;
328
 *       GError *error = NULL;
329
 *
330
 *       cake = bake_cake (baker, cake_data->radius, cake_data->flavor,
331
 *                         cake_data->frosting, cake_data->message,
332
 *                         cancellable, &error);
333
 *       if (cake)
334
 *         g_task_return_pointer (task, cake, g_object_unref);
335
 *       else
336
 *         g_task_return_error (task, error);
337
 *     }
338
 *
339
 *     void
340
 *     baker_bake_cake_async (Baker               *self,
341
 *                            guint                radius,
342
 *                            CakeFlavor           flavor,
343
 *                            CakeFrostingType     frosting,
344
 *                            const char          *message,
345
 *                            GCancellable        *cancellable,
346
 *                            GAsyncReadyCallback  callback,
347
 *                            gpointer             user_data)
348
 *     {
349
 *       CakeData *cake_data;
350
 *       GTask *task;
351
 *
352
 *       cake_data = g_slice_new (CakeData);
353
 *       cake_data->radius = radius;
354
 *       cake_data->flavor = flavor;
355
 *       cake_data->frosting = frosting;
356
 *       cake_data->message = g_strdup (message);
357
 *       task = g_task_new (self, cancellable, callback, user_data);
358
 *       g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free);
359
 *       g_task_run_in_thread (task, bake_cake_thread);
360
 *       g_object_unref (task);
361
 *     }
362
 *
363
 *     Cake *
364
 *     baker_bake_cake_finish (Baker         *self,
365
 *                             GAsyncResult  *result,
366
 *                             GError       **error)
367
 *     {
368
 *       g_return_val_if_fail (g_task_is_valid (result, self), NULL);
369
 *
370
 *       return g_task_propagate_pointer (G_TASK (result), error);
371
 *     }
372
 * ]|
373
 *
374
 * ## Adding cancellability to uncancellable tasks
375
 * 
376
 * Finally, g_task_run_in_thread() and g_task_run_in_thread_sync()
377
 * can be used to turn an uncancellable operation into a
378
 * cancellable one. If you call g_task_set_return_on_cancel(),
379
 * passing %TRUE, then if the task's #GCancellable is cancelled,
380
 * it will return control back to the caller immediately, while
381
 * allowing the task thread to continue running in the background
382
 * (and simply discarding its result when it finally does finish).
383
 * Provided that the task thread is careful about how it uses
384
 * locks and other externally-visible resources, this allows you
385
 * to make "GLib-friendly" asynchronous and cancellable
386
 * synchronous variants of blocking APIs.
387
 *
388
 * Cancelling a task:
389
 *   |[<!-- language="C" -->
390
 *     static void
391
 *     bake_cake_thread (GTask         *task,
392
 *                       gpointer       source_object,
393
 *                       gpointer       task_data,
394
 *                       GCancellable  *cancellable)
395
 *     {
396
 *       Baker *self = source_object;
397
 *       CakeData *cake_data = task_data;
398
 *       Cake *cake;
399
 *       GError *error = NULL;
400
 *
401
 *       cake = bake_cake (baker, cake_data->radius, cake_data->flavor,
402
 *                         cake_data->frosting, cake_data->message,
403
 *                         &error);
404
 *       if (error)
405
 *         {
406
 *           g_task_return_error (task, error);
407
 *           return;
408
 *         }
409
 *
410
 *       // If the task has already been cancelled, then we don't want to add
411
 *       // the cake to the cake cache. Likewise, we don't  want to have the
412
 *       // task get cancelled in the middle of updating the cache.
413
 *       // g_task_set_return_on_cancel() will return %TRUE here if it managed
414
 *       // to disable return-on-cancel, or %FALSE if the task was cancelled
415
 *       // before it could.
416
 *       if (g_task_set_return_on_cancel (task, FALSE))
417
 *         {
418
 *           // If the caller cancels at this point, their
419
 *           // GAsyncReadyCallback won't be invoked until we return,
420
 *           // so we don't have to worry that this code will run at
421
 *           // the same time as that code does. But if there were
422
 *           // other functions that might look at the cake cache,
423
 *           // then we'd probably need a GMutex here as well.
424
 *           baker_add_cake_to_cache (baker, cake);
425
 *           g_task_return_pointer (task, cake, g_object_unref);
426
 *         }
427
 *     }
428
 *
429
 *     void
430
 *     baker_bake_cake_async (Baker               *self,
431
 *                            guint                radius,
432
 *                            CakeFlavor           flavor,
433
 *                            CakeFrostingType     frosting,
434
 *                            const char          *message,
435
 *                            GCancellable        *cancellable,
436
 *                            GAsyncReadyCallback  callback,
437
 *                            gpointer             user_data)
438
 *     {
439
 *       CakeData *cake_data;
440
 *       GTask *task;
441
 *
442
 *       cake_data = g_slice_new (CakeData);
443
 *
444
 *       ...
445
 *
446
 *       task = g_task_new (self, cancellable, callback, user_data);
447
 *       g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free);
448
 *       g_task_set_return_on_cancel (task, TRUE);
449
 *       g_task_run_in_thread (task, bake_cake_thread);
450
 *     }
451
 *
452
 *     Cake *
453
 *     baker_bake_cake_sync (Baker               *self,
454
 *                           guint                radius,
455
 *                           CakeFlavor           flavor,
456
 *                           CakeFrostingType     frosting,
457
 *                           const char          *message,
458
 *                           GCancellable        *cancellable,
459
 *                           GError             **error)
460
 *     {
461
 *       CakeData *cake_data;
462
 *       GTask *task;
463
 *       Cake *cake;
464
 *
465
 *       cake_data = g_slice_new (CakeData);
466
 *
467
 *       ...
468
 *
469
 *       task = g_task_new (self, cancellable, NULL, NULL);
470
 *       g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free);
471
 *       g_task_set_return_on_cancel (task, TRUE);
472
 *       g_task_run_in_thread_sync (task, bake_cake_thread);
473
 *
474
 *       cake = g_task_propagate_pointer (task, error);
475
 *       g_object_unref (task);
476
 *       return cake;
477
 *     }
478
 * ]|
479
 *
480
 * ## Porting from GSimpleAsyncResult
481
 * 
482
 * #GTask's API attempts to be simpler than #GSimpleAsyncResult's
483
 * in several ways:
484
 * - You can save task-specific data with g_task_set_task_data(), and
485
 *   retrieve it later with g_task_get_task_data(). This replaces the
486
 *   abuse of g_simple_async_result_set_op_res_gpointer() for the same
487
 *   purpose with #GSimpleAsyncResult.
488
 * - In addition to the task data, #GTask also keeps track of the
489
 *   [priority][io-priority], #GCancellable, and
490
 *   #GMainContext associated with the task, so tasks that consist of
491
 *   a chain of simpler asynchronous operations will have easy access
492
 *   to those values when starting each sub-task.
493
 * - g_task_return_error_if_cancelled() provides simplified
494
 *   handling for cancellation. In addition, cancellation
495
 *   overrides any other #GTask return value by default, like
496
 *   #GSimpleAsyncResult does when
497
 *   g_simple_async_result_set_check_cancellable() is called.
498
 *   (You can use g_task_set_check_cancellable() to turn off that
499
 *   behavior.) On the other hand, g_task_run_in_thread()
500
 *   guarantees that it will always run your
501
 *   `task_func`, even if the task's #GCancellable
502
 *   is already cancelled before the task gets a chance to run;
503
 *   you can start your `task_func` with a
504
 *   g_task_return_error_if_cancelled() check if you need the
505
 *   old behavior.
506
 * - The "return" methods (eg, g_task_return_pointer())
507
 *   automatically cause the task to be "completed" as well, and
508
 *   there is no need to worry about the "complete" vs "complete
509
 *   in idle" distinction. (#GTask automatically figures out
510
 *   whether the task's callback can be invoked directly, or
511
 *   if it needs to be sent to another #GMainContext, or delayed
512
 *   until the next iteration of the current #GMainContext.)
513
 * - The "finish" functions for #GTask based operations are generally
514
 *   much simpler than #GSimpleAsyncResult ones, normally consisting
515
 *   of only a single call to g_task_propagate_pointer() or the like.
516
 *   Since g_task_propagate_pointer() "steals" the return value from
517
 *   the #GTask, it is not necessary to juggle pointers around to
518
 *   prevent it from being freed twice.
519
 * - With #GSimpleAsyncResult, it was common to call
520
 *   g_simple_async_result_propagate_error() from the
521
 *   `_finish()` wrapper function, and have
522
 *   virtual method implementations only deal with successful
523
 *   returns. This behavior is deprecated, because it makes it
524
 *   difficult for a subclass to chain to a parent class's async
525
 *   methods. Instead, the wrapper function should just be a
526
 *   simple wrapper, and the virtual method should call an
527
 *   appropriate `g_task_propagate_` function.
528
 *   Note that wrapper methods can now use
529
 *   g_async_result_legacy_propagate_error() to do old-style
530
 *   #GSimpleAsyncResult error-returning behavior, and
531
 *   g_async_result_is_tagged() to check if a result is tagged as
532
 *   having come from the `_async()` wrapper
533
 *   function (for "short-circuit" results, such as when passing
534
 *   0 to g_input_stream_read_async()).
535
 */
536
537
/**
538
 * GTask:
539
 *
540
 * The opaque object representing a synchronous or asynchronous task
541
 * and its result.
542
 */
543
544
struct _GTask {
545
  GObject parent_instance;
546
547
  gpointer source_object;
548
  gpointer source_tag;
549
  gchar *name;  /* (owned); may only be modified before the #GTask is threaded */
550
551
  gpointer task_data;
552
  GDestroyNotify task_data_destroy;
553
554
  GMainContext *context;
555
  gint64 creation_time;
556
  gint priority;
557
  GCancellable *cancellable;
558
559
  GAsyncReadyCallback callback;
560
  gpointer callback_data;
561
562
  GTaskThreadFunc task_func;
563
  GMutex lock;
564
  GCond cond;
565
566
  /* This can’t be in the bit field because we access it from TRACE(). */
567
  gboolean thread_cancelled;
568
569
  /* Protected by the lock when task is threaded: */
570
  gboolean thread_complete : 1;
571
  gboolean return_on_cancel : 1;
572
  gboolean : 0;
573
574
  /* Unprotected, but written to when task runs in thread: */
575
  gboolean completed : 1;
576
  gboolean had_error : 1;
577
  gboolean result_set : 1;
578
  gboolean ever_returned : 1;
579
  gboolean : 0;
580
581
  /* Read-only once task runs in thread: */
582
  gboolean check_cancellable : 1;
583
  gboolean synchronous : 1;
584
  gboolean blocking_other_task : 1;
585
586
  GError *error;
587
  union {
588
    gpointer pointer;
589
    gssize   size;
590
    gboolean boolean;
591
  } result;
592
  GDestroyNotify result_destroy;
593
};
594
595
0
#define G_TASK_IS_THREADED(task) ((task)->task_func != NULL)
596
597
struct _GTaskClass
598
{
599
  GObjectClass parent_class;
600
};
601
602
typedef enum
603
{
604
  PROP_COMPLETED = 1,
605
} GTaskProperty;
606
607
static void g_task_async_result_iface_init (GAsyncResultIface *iface);
608
static void g_task_thread_pool_init (void);
609
610
G_DEFINE_TYPE_WITH_CODE (GTask, g_task, G_TYPE_OBJECT,
611
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT,
612
                                                g_task_async_result_iface_init);
613
                         g_task_thread_pool_init ();)
614
615
static GThreadPool *task_pool;
616
static GMutex task_pool_mutex;
617
static GPrivate task_private = G_PRIVATE_INIT (NULL);
618
static GSource *task_pool_manager;
619
static guint64 task_wait_time;
620
static gint tasks_running;
621
622
static guint task_pool_max_counter;
623
static guint tasks_running_counter;
624
625
/* When the task pool fills up and blocks, and the program keeps
626
 * queueing more tasks, we will slowly add more threads to the pool
627
 * (in case the existing tasks are trying to queue subtasks of their
628
 * own) until tasks start completing again. These "overflow" threads
629
 * will only run one task apiece, and then exit, so the pool will
630
 * eventually get back down to its base size.
631
 *
632
 * The base and multiplier below gives us 10 extra threads after about
633
 * a second of blocking, 30 after 5 seconds, 100 after a minute, and
634
 * 200 after 20 minutes.
635
 *
636
 * We specify maximum pool size of 330 to increase the waiting time up
637
 * to around 30 minutes.
638
 */
639
0
#define G_TASK_POOL_SIZE 10
640
0
#define G_TASK_WAIT_TIME_BASE 100000
641
0
#define G_TASK_WAIT_TIME_MULTIPLIER 1.03
642
0
#define G_TASK_WAIT_TIME_MAX_POOL_SIZE 330
643
644
static void
645
g_task_init (GTask *task)
646
0
{
647
0
  task->check_cancellable = TRUE;
648
0
}
649
650
static void
651
g_task_finalize (GObject *object)
652
0
{
653
0
  GTask *task = G_TASK (object);
654
655
0
  g_clear_object (&task->source_object);
656
0
  g_clear_object (&task->cancellable);
657
0
  g_free (task->name);
658
659
0
  if (task->context)
660
0
    g_main_context_unref (task->context);
661
662
0
  if (task->task_data_destroy)
663
0
    task->task_data_destroy (task->task_data);
664
665
0
  if (task->result_destroy && task->result.pointer)
666
0
    task->result_destroy (task->result.pointer);
667
668
0
  if (task->error)
669
0
      g_error_free (task->error);
670
671
0
  if (G_TASK_IS_THREADED (task))
672
0
    {
673
0
      g_mutex_clear (&task->lock);
674
0
      g_cond_clear (&task->cond);
675
0
    }
676
677
0
  G_OBJECT_CLASS (g_task_parent_class)->finalize (object);
678
0
}
679
680
/**
681
 * g_task_new:
682
 * @source_object: (nullable) (type GObject): the #GObject that owns
683
 *   this task, or %NULL.
684
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
685
 * @callback: (scope async): a #GAsyncReadyCallback.
686
 * @callback_data: (closure): user data passed to @callback.
687
 *
688
 * Creates a #GTask acting on @source_object, which will eventually be
689
 * used to invoke @callback in the current
690
 * [thread-default main context][g-main-context-push-thread-default].
691
 *
692
 * Call this in the "start" method of your asynchronous method, and
693
 * pass the #GTask around throughout the asynchronous operation. You
694
 * can use g_task_set_task_data() to attach task-specific data to the
695
 * object, which you can retrieve later via g_task_get_task_data().
696
 *
697
 * By default, if @cancellable is cancelled, then the return value of
698
 * the task will always be %G_IO_ERROR_CANCELLED, even if the task had
699
 * already completed before the cancellation. This allows for
700
 * simplified handling in cases where cancellation may imply that
701
 * other objects that the task depends on have been destroyed. If you
702
 * do not want this behavior, you can use
703
 * g_task_set_check_cancellable() to change it.
704
 *
705
 * Returns: a #GTask.
706
 *
707
 * Since: 2.36
708
 */
709
GTask *
710
g_task_new (gpointer              source_object,
711
            GCancellable         *cancellable,
712
            GAsyncReadyCallback   callback,
713
            gpointer              callback_data)
714
0
{
715
0
  GTask *task;
716
0
  GSource *source;
717
718
0
  task = g_object_new (G_TYPE_TASK, NULL);
719
0
  task->source_object = source_object ? g_object_ref (source_object) : NULL;
720
0
  task->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
721
0
  task->callback = callback;
722
0
  task->callback_data = callback_data;
723
0
  task->context = g_main_context_ref_thread_default ();
724
725
0
  source = g_main_current_source ();
726
0
  if (source)
727
0
    task->creation_time = g_source_get_time (source);
728
729
0
  TRACE (GIO_TASK_NEW (task, source_object, cancellable,
730
0
                       callback, callback_data));
731
732
0
  return task;
733
0
}
734
735
/**
736
 * g_task_report_error:
737
 * @source_object: (nullable) (type GObject): the #GObject that owns
738
 *   this task, or %NULL.
739
 * @callback: (scope async): a #GAsyncReadyCallback.
740
 * @callback_data: (closure): user data passed to @callback.
741
 * @source_tag: an opaque pointer indicating the source of this task
742
 * @error: (transfer full): error to report
743
 *
744
 * Creates a #GTask and then immediately calls g_task_return_error()
745
 * on it. Use this in the wrapper function of an asynchronous method
746
 * when you want to avoid even calling the virtual method. You can
747
 * then use g_async_result_is_tagged() in the finish method wrapper to
748
 * check if the result there is tagged as having been created by the
749
 * wrapper method, and deal with it appropriately if so.
750
 *
751
 * See also g_task_report_new_error().
752
 *
753
 * Since: 2.36
754
 */
755
void
756
g_task_report_error (gpointer             source_object,
757
                     GAsyncReadyCallback  callback,
758
                     gpointer             callback_data,
759
                     gpointer             source_tag,
760
                     GError              *error)
761
0
{
762
0
  GTask *task;
763
764
0
  task = g_task_new (source_object, NULL, callback, callback_data);
765
0
  g_task_set_source_tag (task, source_tag);
766
0
  g_task_set_name (task, G_STRFUNC);
767
0
  g_task_return_error (task, error);
768
0
  g_object_unref (task);
769
0
}
770
771
/**
772
 * g_task_report_new_error:
773
 * @source_object: (nullable) (type GObject): the #GObject that owns
774
 *   this task, or %NULL.
775
 * @callback: (scope async): a #GAsyncReadyCallback.
776
 * @callback_data: (closure): user data passed to @callback.
777
 * @source_tag: an opaque pointer indicating the source of this task
778
 * @domain: a #GQuark.
779
 * @code: an error code.
780
 * @format: a string with format characters.
781
 * @...: a list of values to insert into @format.
782
 *
783
 * Creates a #GTask and then immediately calls
784
 * g_task_return_new_error() on it. Use this in the wrapper function
785
 * of an asynchronous method when you want to avoid even calling the
786
 * virtual method. You can then use g_async_result_is_tagged() in the
787
 * finish method wrapper to check if the result there is tagged as
788
 * having been created by the wrapper method, and deal with it
789
 * appropriately if so.
790
 *
791
 * See also g_task_report_error().
792
 *
793
 * Since: 2.36
794
 */
795
void
796
g_task_report_new_error (gpointer             source_object,
797
                         GAsyncReadyCallback  callback,
798
                         gpointer             callback_data,
799
                         gpointer             source_tag,
800
                         GQuark               domain,
801
                         gint                 code,
802
                         const char          *format,
803
                         ...)
804
0
{
805
0
  GError *error;
806
0
  va_list ap;
807
808
0
  va_start (ap, format);
809
0
  error = g_error_new_valist (domain, code, format, ap);
810
0
  va_end (ap);
811
812
0
  g_task_report_error (source_object, callback, callback_data,
813
0
                       source_tag, error);
814
0
}
815
816
/**
817
 * g_task_set_task_data:
818
 * @task: the #GTask
819
 * @task_data: (nullable): task-specific data
820
 * @task_data_destroy: (nullable): #GDestroyNotify for @task_data
821
 *
822
 * Sets @task's task data (freeing the existing task data, if any).
823
 *
824
 * Since: 2.36
825
 */
826
void
827
g_task_set_task_data (GTask          *task,
828
                      gpointer        task_data,
829
                      GDestroyNotify  task_data_destroy)
830
0
{
831
0
  g_return_if_fail (G_IS_TASK (task));
832
833
0
  if (task->task_data_destroy)
834
0
    task->task_data_destroy (task->task_data);
835
836
0
  task->task_data = task_data;
837
0
  task->task_data_destroy = task_data_destroy;
838
839
0
  TRACE (GIO_TASK_SET_TASK_DATA (task, task_data, task_data_destroy));
840
0
}
841
842
/**
843
 * g_task_set_priority:
844
 * @task: the #GTask
845
 * @priority: the [priority][io-priority] of the request
846
 *
847
 * Sets @task's priority. If you do not call this, it will default to
848
 * %G_PRIORITY_DEFAULT.
849
 *
850
 * This will affect the priority of #GSources created with
851
 * g_task_attach_source() and the scheduling of tasks run in threads,
852
 * and can also be explicitly retrieved later via
853
 * g_task_get_priority().
854
 *
855
 * Since: 2.36
856
 */
857
void
858
g_task_set_priority (GTask *task,
859
                     gint   priority)
860
0
{
861
0
  g_return_if_fail (G_IS_TASK (task));
862
863
0
  task->priority = priority;
864
865
0
  TRACE (GIO_TASK_SET_PRIORITY (task, priority));
866
0
}
867
868
/**
869
 * g_task_set_check_cancellable:
870
 * @task: the #GTask
871
 * @check_cancellable: whether #GTask will check the state of
872
 *   its #GCancellable for you.
873
 *
874
 * Sets or clears @task's check-cancellable flag. If this is %TRUE
875
 * (the default), then g_task_propagate_pointer(), etc, and
876
 * g_task_had_error() will check the task's #GCancellable first, and
877
 * if it has been cancelled, then they will consider the task to have
878
 * returned an "Operation was cancelled" error
879
 * (%G_IO_ERROR_CANCELLED), regardless of any other error or return
880
 * value the task may have had.
881
 *
882
 * If @check_cancellable is %FALSE, then the #GTask will not check the
883
 * cancellable itself, and it is up to @task's owner to do this (eg,
884
 * via g_task_return_error_if_cancelled()).
885
 *
886
 * If you are using g_task_set_return_on_cancel() as well, then
887
 * you must leave check-cancellable set %TRUE.
888
 *
889
 * Since: 2.36
890
 */
891
void
892
g_task_set_check_cancellable (GTask    *task,
893
                              gboolean  check_cancellable)
894
0
{
895
0
  g_return_if_fail (G_IS_TASK (task));
896
0
  g_return_if_fail (check_cancellable || !task->return_on_cancel);
897
898
0
  task->check_cancellable = check_cancellable;
899
0
}
900
901
static void g_task_thread_complete (GTask *task);
902
903
/**
904
 * g_task_set_return_on_cancel:
905
 * @task: the #GTask
906
 * @return_on_cancel: whether the task returns automatically when
907
 *   it is cancelled.
908
 *
909
 * Sets or clears @task's return-on-cancel flag. This is only
910
 * meaningful for tasks run via g_task_run_in_thread() or
911
 * g_task_run_in_thread_sync().
912
 *
913
 * If @return_on_cancel is %TRUE, then cancelling @task's
914
 * #GCancellable will immediately cause it to return, as though the
915
 * task's #GTaskThreadFunc had called
916
 * g_task_return_error_if_cancelled() and then returned.
917
 *
918
 * This allows you to create a cancellable wrapper around an
919
 * uninterruptible function. The #GTaskThreadFunc just needs to be
920
 * careful that it does not modify any externally-visible state after
921
 * it has been cancelled. To do that, the thread should call
922
 * g_task_set_return_on_cancel() again to (atomically) set
923
 * return-on-cancel %FALSE before making externally-visible changes;
924
 * if the task gets cancelled before the return-on-cancel flag could
925
 * be changed, g_task_set_return_on_cancel() will indicate this by
926
 * returning %FALSE.
927
 *
928
 * You can disable and re-enable this flag multiple times if you wish.
929
 * If the task's #GCancellable is cancelled while return-on-cancel is
930
 * %FALSE, then calling g_task_set_return_on_cancel() to set it %TRUE
931
 * again will cause the task to be cancelled at that point.
932
 *
933
 * If the task's #GCancellable is already cancelled before you call
934
 * g_task_run_in_thread()/g_task_run_in_thread_sync(), then the
935
 * #GTaskThreadFunc will still be run (for consistency), but the task
936
 * will also be completed right away.
937
 *
938
 * Returns: %TRUE if @task's return-on-cancel flag was changed to
939
 *   match @return_on_cancel. %FALSE if @task has already been
940
 *   cancelled.
941
 *
942
 * Since: 2.36
943
 */
944
gboolean
945
g_task_set_return_on_cancel (GTask    *task,
946
                             gboolean  return_on_cancel)
947
0
{
948
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
949
0
  g_return_val_if_fail (task->check_cancellable || !return_on_cancel, FALSE);
950
951
0
  if (!G_TASK_IS_THREADED (task))
952
0
    {
953
0
      task->return_on_cancel = return_on_cancel;
954
0
      return TRUE;
955
0
    }
956
957
0
  g_mutex_lock (&task->lock);
958
0
  if (task->thread_cancelled)
959
0
    {
960
0
      if (return_on_cancel && !task->return_on_cancel)
961
0
        {
962
0
          g_mutex_unlock (&task->lock);
963
0
          g_task_thread_complete (task);
964
0
        }
965
0
      else
966
0
        g_mutex_unlock (&task->lock);
967
0
      return FALSE;
968
0
    }
969
0
  task->return_on_cancel = return_on_cancel;
970
0
  g_mutex_unlock (&task->lock);
971
972
0
  return TRUE;
973
0
}
974
975
/**
976
 * g_task_set_source_tag:
977
 * @task: the #GTask
978
 * @source_tag: an opaque pointer indicating the source of this task
979
 *
980
 * Sets @task's source tag. You can use this to tag a task return
981
 * value with a particular pointer (usually a pointer to the function
982
 * doing the tagging) and then later check it using
983
 * g_task_get_source_tag() (or g_async_result_is_tagged()) in the
984
 * task's "finish" function, to figure out if the response came from a
985
 * particular place.
986
 *
987
 * Since: 2.36
988
 */
989
void
990
(g_task_set_source_tag) (GTask    *task,
991
                         gpointer  source_tag)
992
0
{
993
0
  g_return_if_fail (G_IS_TASK (task));
994
995
0
  task->source_tag = source_tag;
996
997
0
  TRACE (GIO_TASK_SET_SOURCE_TAG (task, source_tag));
998
0
}
999
1000
/**
1001
 * g_task_set_name:
1002
 * @task: a #GTask
1003
 * @name: (nullable): a human readable name for the task, or %NULL to unset it
1004
 *
1005
 * Sets @task’s name, used in debugging and profiling. The name defaults to
1006
 * %NULL.
1007
 *
1008
 * The task name should describe in a human readable way what the task does.
1009
 * For example, ‘Open file’ or ‘Connect to network host’. It is used to set the
1010
 * name of the #GSource used for idle completion of the task.
1011
 *
1012
 * This function may only be called before the @task is first used in a thread
1013
 * other than the one it was constructed in.
1014
 *
1015
 * Since: 2.60
1016
 */
1017
void
1018
g_task_set_name (GTask       *task,
1019
                 const gchar *name)
1020
0
{
1021
0
  gchar *new_name;
1022
1023
0
  g_return_if_fail (G_IS_TASK (task));
1024
1025
0
  new_name = g_strdup (name);
1026
0
  g_free (task->name);
1027
0
  task->name = g_steal_pointer (&new_name);
1028
0
}
1029
1030
/**
1031
 * g_task_get_source_object:
1032
 * @task: a #GTask
1033
 *
1034
 * Gets the source object from @task. Like
1035
 * g_async_result_get_source_object(), but does not ref the object.
1036
 *
1037
 * Returns: (transfer none) (nullable) (type GObject): @task's source object, or %NULL
1038
 *
1039
 * Since: 2.36
1040
 */
1041
gpointer
1042
g_task_get_source_object (GTask *task)
1043
0
{
1044
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1045
1046
0
  return task->source_object;
1047
0
}
1048
1049
static GObject *
1050
g_task_ref_source_object (GAsyncResult *res)
1051
0
{
1052
0
  GTask *task = G_TASK (res);
1053
1054
0
  if (task->source_object)
1055
0
    return g_object_ref (task->source_object);
1056
0
  else
1057
0
    return NULL;
1058
0
}
1059
1060
/**
1061
 * g_task_get_task_data:
1062
 * @task: a #GTask
1063
 *
1064
 * Gets @task's `task_data`.
1065
 *
1066
 * Returns: (transfer none): @task's `task_data`.
1067
 *
1068
 * Since: 2.36
1069
 */
1070
gpointer
1071
g_task_get_task_data (GTask *task)
1072
0
{
1073
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1074
1075
0
  return task->task_data;
1076
0
}
1077
1078
/**
1079
 * g_task_get_priority:
1080
 * @task: a #GTask
1081
 *
1082
 * Gets @task's priority
1083
 *
1084
 * Returns: @task's priority
1085
 *
1086
 * Since: 2.36
1087
 */
1088
gint
1089
g_task_get_priority (GTask *task)
1090
0
{
1091
0
  g_return_val_if_fail (G_IS_TASK (task), G_PRIORITY_DEFAULT);
1092
1093
0
  return task->priority;
1094
0
}
1095
1096
/**
1097
 * g_task_get_context:
1098
 * @task: a #GTask
1099
 *
1100
 * Gets the #GMainContext that @task will return its result in (that
1101
 * is, the context that was the
1102
 * [thread-default main context][g-main-context-push-thread-default]
1103
 * at the point when @task was created).
1104
 *
1105
 * This will always return a non-%NULL value, even if the task's
1106
 * context is the default #GMainContext.
1107
 *
1108
 * Returns: (transfer none): @task's #GMainContext
1109
 *
1110
 * Since: 2.36
1111
 */
1112
GMainContext *
1113
g_task_get_context (GTask *task)
1114
0
{
1115
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1116
1117
0
  return task->context;
1118
0
}
1119
1120
/**
1121
 * g_task_get_cancellable:
1122
 * @task: a #GTask
1123
 *
1124
 * Gets @task's #GCancellable
1125
 *
1126
 * Returns: (transfer none): @task's #GCancellable
1127
 *
1128
 * Since: 2.36
1129
 */
1130
GCancellable *
1131
g_task_get_cancellable (GTask *task)
1132
0
{
1133
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1134
1135
0
  return task->cancellable;
1136
0
}
1137
1138
/**
1139
 * g_task_get_check_cancellable:
1140
 * @task: the #GTask
1141
 *
1142
 * Gets @task's check-cancellable flag. See
1143
 * g_task_set_check_cancellable() for more details.
1144
 *
1145
 * Since: 2.36
1146
 */
1147
gboolean
1148
g_task_get_check_cancellable (GTask *task)
1149
0
{
1150
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1151
1152
  /* Convert from a bit field to a boolean. */
1153
0
  return task->check_cancellable ? TRUE : FALSE;
1154
0
}
1155
1156
/**
1157
 * g_task_get_return_on_cancel:
1158
 * @task: the #GTask
1159
 *
1160
 * Gets @task's return-on-cancel flag. See
1161
 * g_task_set_return_on_cancel() for more details.
1162
 *
1163
 * Since: 2.36
1164
 */
1165
gboolean
1166
g_task_get_return_on_cancel (GTask *task)
1167
0
{
1168
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1169
1170
  /* Convert from a bit field to a boolean. */
1171
0
  return task->return_on_cancel ? TRUE : FALSE;
1172
0
}
1173
1174
/**
1175
 * g_task_get_source_tag:
1176
 * @task: a #GTask
1177
 *
1178
 * Gets @task's source tag. See g_task_set_source_tag().
1179
 *
1180
 * Returns: (transfer none): @task's source tag
1181
 *
1182
 * Since: 2.36
1183
 */
1184
gpointer
1185
g_task_get_source_tag (GTask *task)
1186
0
{
1187
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1188
1189
0
  return task->source_tag;
1190
0
}
1191
1192
/**
1193
 * g_task_get_name:
1194
 * @task: a #GTask
1195
 *
1196
 * Gets @task’s name. See g_task_set_name().
1197
 *
1198
 * Returns: (nullable) (transfer none): @task’s name, or %NULL
1199
 * Since: 2.60
1200
 */
1201
const gchar *
1202
g_task_get_name (GTask *task)
1203
0
{
1204
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1205
1206
0
  return task->name;
1207
0
}
1208
1209
static void
1210
g_task_return_now (GTask *task)
1211
0
{
1212
0
  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object, task->callback,
1213
0
                                 task->callback_data));
1214
1215
0
  g_main_context_push_thread_default (task->context);
1216
1217
0
  if (task->callback != NULL)
1218
0
    {
1219
0
      task->callback (task->source_object,
1220
0
                      G_ASYNC_RESULT (task),
1221
0
                      task->callback_data);
1222
0
    }
1223
1224
0
  task->completed = TRUE;
1225
0
  g_object_notify (G_OBJECT (task), "completed");
1226
1227
0
  g_main_context_pop_thread_default (task->context);
1228
0
}
1229
1230
static gboolean
1231
complete_in_idle_cb (gpointer task)
1232
0
{
1233
0
  g_task_return_now (task);
1234
0
  g_object_unref (task);
1235
0
  return FALSE;
1236
0
}
1237
1238
typedef enum {
1239
  G_TASK_RETURN_SUCCESS,
1240
  G_TASK_RETURN_ERROR,
1241
  G_TASK_RETURN_FROM_THREAD
1242
} GTaskReturnType;
1243
1244
static void
1245
g_task_return (GTask           *task,
1246
               GTaskReturnType  type)
1247
0
{
1248
0
  GSource *source;
1249
0
  gchar *source_name = NULL;
1250
1251
0
  if (type != G_TASK_RETURN_FROM_THREAD)
1252
0
    task->ever_returned = TRUE;
1253
1254
0
  if (type == G_TASK_RETURN_SUCCESS)
1255
0
    task->result_set = TRUE;
1256
1257
0
  if (task->synchronous)
1258
0
    return;
1259
1260
  /* Normally we want to invoke the task's callback when its return
1261
   * value is set. But if the task is running in a thread, then we
1262
   * want to wait until after the task_func returns, to simplify
1263
   * locking/refcounting/etc.
1264
   */
1265
0
  if (G_TASK_IS_THREADED (task) && type != G_TASK_RETURN_FROM_THREAD)
1266
0
    return;
1267
1268
0
  g_object_ref (task);
1269
1270
  /* See if we can complete the task immediately. First, we have to be
1271
   * running inside the task's thread/GMainContext.
1272
   */
1273
0
  source = g_main_current_source ();
1274
0
  if (source && g_source_get_context (source) == task->context)
1275
0
    {
1276
      /* Second, we can only complete immediately if this is not the
1277
       * same iteration of the main loop that the task was created in.
1278
       */
1279
0
      if (g_source_get_time (source) > task->creation_time)
1280
0
        {
1281
          /* Finally, if the task has been cancelled, we shouldn't
1282
           * return synchronously from inside the
1283
           * GCancellable::cancelled handler. It's easier to run
1284
           * another iteration of the main loop than tracking how the
1285
           * cancellation was handled.
1286
           */
1287
0
          if (!g_cancellable_is_cancelled (task->cancellable))
1288
0
            {
1289
0
              g_task_return_now (task);
1290
0
              g_object_unref (task);
1291
0
              return;
1292
0
            }
1293
0
        }
1294
0
    }
1295
1296
  /* Otherwise, complete in the next iteration */
1297
0
  source = g_idle_source_new ();
1298
0
  source_name = g_strdup_printf ("[gio] %s complete_in_idle_cb",
1299
0
                                 (task->name != NULL) ? task->name : "(unnamed)");
1300
0
  g_source_set_name (source, source_name);
1301
0
  g_free (source_name);
1302
0
  g_task_attach_source (task, source, complete_in_idle_cb);
1303
0
  g_source_unref (source);
1304
0
}
1305
1306
1307
/**
1308
 * GTaskThreadFunc:
1309
 * @task: the #GTask
1310
 * @source_object: (type GObject): @task's source object
1311
 * @task_data: @task's task data
1312
 * @cancellable: @task's #GCancellable, or %NULL
1313
 *
1314
 * The prototype for a task function to be run in a thread via
1315
 * g_task_run_in_thread() or g_task_run_in_thread_sync().
1316
 *
1317
 * If the return-on-cancel flag is set on @task, and @cancellable gets
1318
 * cancelled, then the #GTask will be completed immediately (as though
1319
 * g_task_return_error_if_cancelled() had been called), without
1320
 * waiting for the task function to complete. However, the task
1321
 * function will continue running in its thread in the background. The
1322
 * function therefore needs to be careful about how it uses
1323
 * externally-visible state in this case. See
1324
 * g_task_set_return_on_cancel() for more details.
1325
 *
1326
 * Other than in that case, @task will be completed when the
1327
 * #GTaskThreadFunc returns, not when it calls a
1328
 * `g_task_return_` function.
1329
 *
1330
 * Since: 2.36
1331
 */
1332
1333
static void task_thread_cancelled (GCancellable *cancellable,
1334
                                   gpointer      user_data);
1335
1336
static void
1337
g_task_thread_complete (GTask *task)
1338
0
{
1339
0
  g_mutex_lock (&task->lock);
1340
0
  if (task->thread_complete)
1341
0
    {
1342
      /* The task belatedly completed after having been cancelled
1343
       * (or was cancelled in the midst of being completed).
1344
       */
1345
0
      g_mutex_unlock (&task->lock);
1346
0
      return;
1347
0
    }
1348
1349
0
  TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
1350
1351
0
  task->thread_complete = TRUE;
1352
0
  g_mutex_unlock (&task->lock);
1353
1354
0
  if (task->cancellable)
1355
0
    g_signal_handlers_disconnect_by_func (task->cancellable, task_thread_cancelled, task);
1356
1357
0
  if (task->synchronous)
1358
0
    g_cond_signal (&task->cond);
1359
0
  else
1360
0
    g_task_return (task, G_TASK_RETURN_FROM_THREAD);
1361
0
}
1362
1363
static gboolean
1364
task_pool_manager_timeout (gpointer user_data)
1365
0
{
1366
0
  g_mutex_lock (&task_pool_mutex);
1367
0
  g_thread_pool_set_max_threads (task_pool, tasks_running + 1, NULL);
1368
0
  g_trace_set_int64_counter (task_pool_max_counter, tasks_running + 1);
1369
0
  g_source_set_ready_time (task_pool_manager, -1);
1370
0
  g_mutex_unlock (&task_pool_mutex);
1371
1372
0
  return TRUE;
1373
0
}
1374
1375
static void
1376
g_task_thread_setup (void)
1377
0
{
1378
0
  g_private_set (&task_private, GUINT_TO_POINTER (TRUE));
1379
0
  g_mutex_lock (&task_pool_mutex);
1380
0
  tasks_running++;
1381
1382
0
  g_trace_set_int64_counter (tasks_running_counter, tasks_running);
1383
1384
0
  if (tasks_running == G_TASK_POOL_SIZE)
1385
0
    task_wait_time = G_TASK_WAIT_TIME_BASE;
1386
0
  else if (tasks_running > G_TASK_POOL_SIZE && tasks_running < G_TASK_WAIT_TIME_MAX_POOL_SIZE)
1387
0
    task_wait_time *= G_TASK_WAIT_TIME_MULTIPLIER;
1388
1389
0
  if (tasks_running >= G_TASK_POOL_SIZE)
1390
0
    g_source_set_ready_time (task_pool_manager, g_get_monotonic_time () + task_wait_time);
1391
1392
0
  g_mutex_unlock (&task_pool_mutex);
1393
0
}
1394
1395
static void
1396
g_task_thread_cleanup (void)
1397
0
{
1398
0
  gint tasks_pending;
1399
1400
0
  g_mutex_lock (&task_pool_mutex);
1401
0
  tasks_pending = g_thread_pool_unprocessed (task_pool);
1402
1403
0
  if (tasks_running > G_TASK_POOL_SIZE)
1404
0
    {
1405
0
      g_thread_pool_set_max_threads (task_pool, tasks_running - 1, NULL);
1406
0
      g_trace_set_int64_counter (task_pool_max_counter, tasks_running - 1);
1407
0
    }
1408
0
  else if (tasks_running + tasks_pending < G_TASK_POOL_SIZE)
1409
0
    g_source_set_ready_time (task_pool_manager, -1);
1410
1411
0
  if (tasks_running > G_TASK_POOL_SIZE && tasks_running < G_TASK_WAIT_TIME_MAX_POOL_SIZE)
1412
0
    task_wait_time /= G_TASK_WAIT_TIME_MULTIPLIER;
1413
1414
0
  tasks_running--;
1415
1416
0
  g_trace_set_int64_counter (tasks_running_counter, tasks_running);
1417
1418
0
  g_mutex_unlock (&task_pool_mutex);
1419
0
  g_private_set (&task_private, GUINT_TO_POINTER (FALSE));
1420
0
}
1421
1422
static void
1423
g_task_thread_pool_thread (gpointer thread_data,
1424
                           gpointer pool_data)
1425
0
{
1426
0
  GTask *task = thread_data;
1427
1428
0
  g_task_thread_setup ();
1429
1430
0
  task->task_func (task, task->source_object, task->task_data,
1431
0
                   task->cancellable);
1432
0
  g_task_thread_complete (task);
1433
0
  g_object_unref (task);
1434
1435
0
  g_task_thread_cleanup ();
1436
0
}
1437
1438
static void
1439
task_thread_cancelled (GCancellable *cancellable,
1440
                       gpointer      user_data)
1441
0
{
1442
0
  GTask *task = user_data;
1443
1444
  /* Move this task to the front of the queue - no need for
1445
   * a complete resorting of the queue.
1446
   */
1447
0
  g_thread_pool_move_to_front (task_pool, task);
1448
1449
0
  g_mutex_lock (&task->lock);
1450
0
  task->thread_cancelled = TRUE;
1451
1452
0
  if (!task->return_on_cancel)
1453
0
    {
1454
0
      g_mutex_unlock (&task->lock);
1455
0
      return;
1456
0
    }
1457
1458
  /* We don't actually set task->error; g_task_return_error() doesn't
1459
   * use a lock, and g_task_propagate_error() will call
1460
   * g_cancellable_set_error_if_cancelled() anyway.
1461
   */
1462
0
  g_mutex_unlock (&task->lock);
1463
0
  g_task_thread_complete (task);
1464
0
}
1465
1466
static void
1467
task_thread_cancelled_disconnect_notify (gpointer  task,
1468
                                         GClosure *closure)
1469
0
{
1470
0
  g_object_unref (task);
1471
0
}
1472
1473
static void
1474
g_task_start_task_thread (GTask           *task,
1475
                          GTaskThreadFunc  task_func)
1476
0
{
1477
0
  g_mutex_init (&task->lock);
1478
0
  g_cond_init (&task->cond);
1479
1480
0
  g_mutex_lock (&task->lock);
1481
1482
0
  TRACE (GIO_TASK_BEFORE_RUN_IN_THREAD (task, task_func));
1483
1484
0
  task->task_func = task_func;
1485
1486
0
  if (task->cancellable)
1487
0
    {
1488
0
      if (task->return_on_cancel &&
1489
0
          g_cancellable_set_error_if_cancelled (task->cancellable,
1490
0
                                                &task->error))
1491
0
        {
1492
0
          task->thread_cancelled = task->thread_complete = TRUE;
1493
0
          TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
1494
0
          g_thread_pool_push (task_pool, g_object_ref (task), NULL);
1495
0
          return;
1496
0
        }
1497
1498
      /* This introduces a reference count loop between the GTask and
1499
       * GCancellable, but is necessary to avoid a race on finalising the GTask
1500
       * between task_thread_cancelled() (in one thread) and
1501
       * g_task_thread_complete() (in another).
1502
       *
1503
       * Accordingly, the signal handler *must* be removed once the task has
1504
       * completed.
1505
       */
1506
0
      g_signal_connect_data (task->cancellable, "cancelled",
1507
0
                             G_CALLBACK (task_thread_cancelled),
1508
0
                             g_object_ref (task),
1509
0
                             task_thread_cancelled_disconnect_notify, 0);
1510
0
    }
1511
1512
0
  if (g_private_get (&task_private))
1513
0
    task->blocking_other_task = TRUE;
1514
0
  g_thread_pool_push (task_pool, g_object_ref (task), NULL);
1515
0
}
1516
1517
/**
1518
 * g_task_run_in_thread:
1519
 * @task: a #GTask
1520
 * @task_func: (scope async): a #GTaskThreadFunc
1521
 *
1522
 * Runs @task_func in another thread. When @task_func returns, @task's
1523
 * #GAsyncReadyCallback will be invoked in @task's #GMainContext.
1524
 *
1525
 * This takes a ref on @task until the task completes.
1526
 *
1527
 * See #GTaskThreadFunc for more details about how @task_func is handled.
1528
 *
1529
 * Although GLib currently rate-limits the tasks queued via
1530
 * g_task_run_in_thread(), you should not assume that it will always
1531
 * do this. If you have a very large number of tasks to run, but don't
1532
 * want them to all run at once, you should only queue a limited
1533
 * number of them at a time.
1534
 *
1535
 * Since: 2.36
1536
 */
1537
void
1538
g_task_run_in_thread (GTask           *task,
1539
                      GTaskThreadFunc  task_func)
1540
0
{
1541
0
  g_return_if_fail (G_IS_TASK (task));
1542
1543
0
  g_object_ref (task);
1544
0
  g_task_start_task_thread (task, task_func);
1545
1546
  /* The task may already be cancelled, or g_thread_pool_push() may
1547
   * have failed.
1548
   */
1549
0
  if (task->thread_complete)
1550
0
    {
1551
0
      g_mutex_unlock (&task->lock);
1552
0
      g_task_return (task, G_TASK_RETURN_FROM_THREAD);
1553
0
    }
1554
0
  else
1555
0
    g_mutex_unlock (&task->lock);
1556
1557
0
  g_object_unref (task);
1558
0
}
1559
1560
/**
1561
 * g_task_run_in_thread_sync:
1562
 * @task: a #GTask
1563
 * @task_func: (scope async): a #GTaskThreadFunc
1564
 *
1565
 * Runs @task_func in another thread, and waits for it to return or be
1566
 * cancelled. You can use g_task_propagate_pointer(), etc, afterward
1567
 * to get the result of @task_func.
1568
 *
1569
 * See #GTaskThreadFunc for more details about how @task_func is handled.
1570
 *
1571
 * Normally this is used with tasks created with a %NULL
1572
 * `callback`, but note that even if the task does
1573
 * have a callback, it will not be invoked when @task_func returns.
1574
 * #GTask:completed will be set to %TRUE just before this function returns.
1575
 *
1576
 * Although GLib currently rate-limits the tasks queued via
1577
 * g_task_run_in_thread_sync(), you should not assume that it will
1578
 * always do this. If you have a very large number of tasks to run,
1579
 * but don't want them to all run at once, you should only queue a
1580
 * limited number of them at a time.
1581
 *
1582
 * Since: 2.36
1583
 */
1584
void
1585
g_task_run_in_thread_sync (GTask           *task,
1586
                           GTaskThreadFunc  task_func)
1587
0
{
1588
0
  g_return_if_fail (G_IS_TASK (task));
1589
1590
0
  g_object_ref (task);
1591
1592
0
  task->synchronous = TRUE;
1593
0
  g_task_start_task_thread (task, task_func);
1594
1595
0
  while (!task->thread_complete)
1596
0
    g_cond_wait (&task->cond, &task->lock);
1597
1598
0
  g_mutex_unlock (&task->lock);
1599
1600
0
  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object,
1601
0
                                 NULL  /* callback */,
1602
0
                                 NULL  /* callback data */));
1603
1604
  /* Notify of completion in this thread. */
1605
0
  task->completed = TRUE;
1606
0
  g_object_notify (G_OBJECT (task), "completed");
1607
1608
0
  g_object_unref (task);
1609
0
}
1610
1611
/**
1612
 * g_task_attach_source:
1613
 * @task: a #GTask
1614
 * @source: the source to attach
1615
 * @callback: the callback to invoke when @source triggers
1616
 *
1617
 * A utility function for dealing with async operations where you need
1618
 * to wait for a #GSource to trigger. Attaches @source to @task's
1619
 * #GMainContext with @task's [priority][io-priority], and sets @source's
1620
 * callback to @callback, with @task as the callback's `user_data`.
1621
 *
1622
 * It will set the @source’s name to the task’s name (as set with
1623
 * g_task_set_name()), if one has been set.
1624
 *
1625
 * This takes a reference on @task until @source is destroyed.
1626
 *
1627
 * Since: 2.36
1628
 */
1629
void
1630
g_task_attach_source (GTask       *task,
1631
                      GSource     *source,
1632
                      GSourceFunc  callback)
1633
0
{
1634
0
  g_return_if_fail (G_IS_TASK (task));
1635
1636
0
  g_source_set_callback (source, callback,
1637
0
                         g_object_ref (task), g_object_unref);
1638
0
  g_source_set_priority (source, task->priority);
1639
0
  if (task->name != NULL)
1640
0
    g_source_set_name (source, task->name);
1641
1642
0
  g_source_attach (source, task->context);
1643
0
}
1644
1645
1646
static gboolean
1647
g_task_propagate_error (GTask   *task,
1648
                        GError **error)
1649
0
{
1650
0
  gboolean error_set;
1651
1652
0
  if (task->check_cancellable &&
1653
0
      g_cancellable_set_error_if_cancelled (task->cancellable, error))
1654
0
    error_set = TRUE;
1655
0
  else if (task->error)
1656
0
    {
1657
0
      g_propagate_error (error, task->error);
1658
0
      task->error = NULL;
1659
0
      task->had_error = TRUE;
1660
0
      error_set = TRUE;
1661
0
    }
1662
0
  else
1663
0
    error_set = FALSE;
1664
1665
0
  TRACE (GIO_TASK_PROPAGATE (task, error_set));
1666
1667
0
  return error_set;
1668
0
}
1669
1670
/**
1671
 * g_task_return_pointer:
1672
 * @task: a #GTask
1673
 * @result: (nullable) (transfer full): the pointer result of a task
1674
 *     function
1675
 * @result_destroy: (nullable): a #GDestroyNotify function.
1676
 *
1677
 * Sets @task's result to @result and completes the task. If @result
1678
 * is not %NULL, then @result_destroy will be used to free @result if
1679
 * the caller does not take ownership of it with
1680
 * g_task_propagate_pointer().
1681
 *
1682
 * "Completes the task" means that for an ordinary asynchronous task
1683
 * it will either invoke the task's callback, or else queue that
1684
 * callback to be invoked in the proper #GMainContext, or in the next
1685
 * iteration of the current #GMainContext. For a task run via
1686
 * g_task_run_in_thread() or g_task_run_in_thread_sync(), calling this
1687
 * method will save @result to be returned to the caller later, but
1688
 * the task will not actually be completed until the #GTaskThreadFunc
1689
 * exits.
1690
 *
1691
 * Note that since the task may be completed before returning from
1692
 * g_task_return_pointer(), you cannot assume that @result is still
1693
 * valid after calling this, unless you are still holding another
1694
 * reference on it.
1695
 *
1696
 * Since: 2.36
1697
 */
1698
void
1699
g_task_return_pointer (GTask          *task,
1700
                       gpointer        result,
1701
                       GDestroyNotify  result_destroy)
1702
0
{
1703
0
  g_return_if_fail (G_IS_TASK (task));
1704
0
  g_return_if_fail (!task->ever_returned);
1705
1706
0
  task->result.pointer = result;
1707
0
  task->result_destroy = result_destroy;
1708
1709
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1710
0
}
1711
1712
/**
1713
 * g_task_propagate_pointer:
1714
 * @task: a #GTask
1715
 * @error: return location for a #GError
1716
 *
1717
 * Gets the result of @task as a pointer, and transfers ownership
1718
 * of that value to the caller.
1719
 *
1720
 * If the task resulted in an error, or was cancelled, then this will
1721
 * instead return %NULL and set @error.
1722
 *
1723
 * Since this method transfers ownership of the return value (or
1724
 * error) to the caller, you may only call it once.
1725
 *
1726
 * Returns: (transfer full): the task result, or %NULL on error
1727
 *
1728
 * Since: 2.36
1729
 */
1730
gpointer
1731
g_task_propagate_pointer (GTask   *task,
1732
                          GError **error)
1733
0
{
1734
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1735
1736
0
  if (g_task_propagate_error (task, error))
1737
0
    return NULL;
1738
1739
0
  g_return_val_if_fail (task->result_set, NULL);
1740
1741
0
  task->result_destroy = NULL;
1742
0
  task->result_set = FALSE;
1743
0
  return task->result.pointer;
1744
0
}
1745
1746
/**
1747
 * g_task_return_int:
1748
 * @task: a #GTask.
1749
 * @result: the integer (#gssize) result of a task function.
1750
 *
1751
 * Sets @task's result to @result and completes the task (see
1752
 * g_task_return_pointer() for more discussion of exactly what this
1753
 * means).
1754
 *
1755
 * Since: 2.36
1756
 */
1757
void
1758
g_task_return_int (GTask  *task,
1759
                   gssize  result)
1760
0
{
1761
0
  g_return_if_fail (G_IS_TASK (task));
1762
0
  g_return_if_fail (!task->ever_returned);
1763
1764
0
  task->result.size = result;
1765
1766
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1767
0
}
1768
1769
/**
1770
 * g_task_propagate_int:
1771
 * @task: a #GTask.
1772
 * @error: return location for a #GError
1773
 *
1774
 * Gets the result of @task as an integer (#gssize).
1775
 *
1776
 * If the task resulted in an error, or was cancelled, then this will
1777
 * instead return -1 and set @error.
1778
 *
1779
 * Since this method transfers ownership of the return value (or
1780
 * error) to the caller, you may only call it once.
1781
 *
1782
 * Returns: the task result, or -1 on error
1783
 *
1784
 * Since: 2.36
1785
 */
1786
gssize
1787
g_task_propagate_int (GTask   *task,
1788
                      GError **error)
1789
0
{
1790
0
  g_return_val_if_fail (G_IS_TASK (task), -1);
1791
1792
0
  if (g_task_propagate_error (task, error))
1793
0
    return -1;
1794
1795
0
  g_return_val_if_fail (task->result_set, -1);
1796
1797
0
  task->result_set = FALSE;
1798
0
  return task->result.size;
1799
0
}
1800
1801
/**
1802
 * g_task_return_boolean:
1803
 * @task: a #GTask.
1804
 * @result: the #gboolean result of a task function.
1805
 *
1806
 * Sets @task's result to @result and completes the task (see
1807
 * g_task_return_pointer() for more discussion of exactly what this
1808
 * means).
1809
 *
1810
 * Since: 2.36
1811
 */
1812
void
1813
g_task_return_boolean (GTask    *task,
1814
                       gboolean  result)
1815
0
{
1816
0
  g_return_if_fail (G_IS_TASK (task));
1817
0
  g_return_if_fail (!task->ever_returned);
1818
1819
0
  task->result.boolean = result;
1820
1821
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1822
0
}
1823
1824
/**
1825
 * g_task_propagate_boolean:
1826
 * @task: a #GTask.
1827
 * @error: return location for a #GError
1828
 *
1829
 * Gets the result of @task as a #gboolean.
1830
 *
1831
 * If the task resulted in an error, or was cancelled, then this will
1832
 * instead return %FALSE and set @error.
1833
 *
1834
 * Since this method transfers ownership of the return value (or
1835
 * error) to the caller, you may only call it once.
1836
 *
1837
 * Returns: the task result, or %FALSE on error
1838
 *
1839
 * Since: 2.36
1840
 */
1841
gboolean
1842
g_task_propagate_boolean (GTask   *task,
1843
                          GError **error)
1844
0
{
1845
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1846
1847
0
  if (g_task_propagate_error (task, error))
1848
0
    return FALSE;
1849
1850
0
  g_return_val_if_fail (task->result_set, FALSE);
1851
1852
0
  task->result_set = FALSE;
1853
0
  return task->result.boolean;
1854
0
}
1855
1856
/**
1857
 * g_task_return_error:
1858
 * @task: a #GTask.
1859
 * @error: (transfer full): the #GError result of a task function.
1860
 *
1861
 * Sets @task's result to @error (which @task assumes ownership of)
1862
 * and completes the task (see g_task_return_pointer() for more
1863
 * discussion of exactly what this means).
1864
 *
1865
 * Note that since the task takes ownership of @error, and since the
1866
 * task may be completed before returning from g_task_return_error(),
1867
 * you cannot assume that @error is still valid after calling this.
1868
 * Call g_error_copy() on the error if you need to keep a local copy
1869
 * as well.
1870
 *
1871
 * See also g_task_return_new_error().
1872
 *
1873
 * Since: 2.36
1874
 */
1875
void
1876
g_task_return_error (GTask  *task,
1877
                     GError *error)
1878
0
{
1879
0
  g_return_if_fail (G_IS_TASK (task));
1880
0
  g_return_if_fail (!task->ever_returned);
1881
0
  g_return_if_fail (error != NULL);
1882
1883
0
  task->error = error;
1884
1885
0
  g_task_return (task, G_TASK_RETURN_ERROR);
1886
0
}
1887
1888
/**
1889
 * g_task_return_new_error:
1890
 * @task: a #GTask.
1891
 * @domain: a #GQuark.
1892
 * @code: an error code.
1893
 * @format: a string with format characters.
1894
 * @...: a list of values to insert into @format.
1895
 *
1896
 * Sets @task's result to a new #GError created from @domain, @code,
1897
 * @format, and the remaining arguments, and completes the task (see
1898
 * g_task_return_pointer() for more discussion of exactly what this
1899
 * means).
1900
 *
1901
 * See also g_task_return_error().
1902
 *
1903
 * Since: 2.36
1904
 */
1905
void
1906
g_task_return_new_error (GTask           *task,
1907
                         GQuark           domain,
1908
                         gint             code,
1909
                         const char      *format,
1910
                         ...)
1911
0
{
1912
0
  GError *error;
1913
0
  va_list args;
1914
1915
0
  va_start (args, format);
1916
0
  error = g_error_new_valist (domain, code, format, args);
1917
0
  va_end (args);
1918
1919
0
  g_task_return_error (task, error);
1920
0
}
1921
1922
/**
1923
 * g_task_return_error_if_cancelled:
1924
 * @task: a #GTask
1925
 *
1926
 * Checks if @task's #GCancellable has been cancelled, and if so, sets
1927
 * @task's error accordingly and completes the task (see
1928
 * g_task_return_pointer() for more discussion of exactly what this
1929
 * means).
1930
 *
1931
 * Returns: %TRUE if @task has been cancelled, %FALSE if not
1932
 *
1933
 * Since: 2.36
1934
 */
1935
gboolean
1936
g_task_return_error_if_cancelled (GTask *task)
1937
0
{
1938
0
  GError *error = NULL;
1939
1940
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1941
0
  g_return_val_if_fail (!task->ever_returned, FALSE);
1942
1943
0
  if (g_cancellable_set_error_if_cancelled (task->cancellable, &error))
1944
0
    {
1945
      /* We explicitly set task->error so this works even when
1946
       * check-cancellable is not set.
1947
       */
1948
0
      g_clear_error (&task->error);
1949
0
      task->error = error;
1950
1951
0
      g_task_return (task, G_TASK_RETURN_ERROR);
1952
0
      return TRUE;
1953
0
    }
1954
0
  else
1955
0
    return FALSE;
1956
0
}
1957
1958
/**
1959
 * g_task_had_error:
1960
 * @task: a #GTask.
1961
 *
1962
 * Tests if @task resulted in an error.
1963
 *
1964
 * Returns: %TRUE if the task resulted in an error, %FALSE otherwise.
1965
 *
1966
 * Since: 2.36
1967
 */
1968
gboolean
1969
g_task_had_error (GTask *task)
1970
0
{
1971
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1972
1973
0
  if (task->error != NULL || task->had_error)
1974
0
    return TRUE;
1975
1976
0
  if (task->check_cancellable && g_cancellable_is_cancelled (task->cancellable))
1977
0
    return TRUE;
1978
1979
0
  return FALSE;
1980
0
}
1981
1982
static void
1983
value_free (gpointer value)
1984
0
{
1985
0
  g_value_unset (value);
1986
0
  g_free (value);
1987
0
}
1988
1989
/**
1990
 * g_task_return_value:
1991
 * @task: a #GTask
1992
 * @result: (nullable) (transfer none): the #GValue result of
1993
 *                                      a task function
1994
 *
1995
 * Sets @task's result to @result (by copying it) and completes the task.
1996
 *
1997
 * If @result is %NULL then a #GValue of type #G_TYPE_POINTER
1998
 * with a value of %NULL will be used for the result.
1999
 *
2000
 * This is a very generic low-level method intended primarily for use
2001
 * by language bindings; for C code, g_task_return_pointer() and the
2002
 * like will normally be much easier to use.
2003
 *
2004
 * Since: 2.64
2005
 */
2006
void
2007
g_task_return_value (GTask  *task,
2008
                     GValue *result)
2009
0
{
2010
0
  GValue *value;
2011
2012
0
  g_return_if_fail (G_IS_TASK (task));
2013
0
  g_return_if_fail (!task->ever_returned);
2014
2015
0
  value = g_new0 (GValue, 1);
2016
2017
0
  if (result == NULL)
2018
0
    {
2019
0
      g_value_init (value, G_TYPE_POINTER);
2020
0
      g_value_set_pointer (value, NULL);
2021
0
    }
2022
0
  else
2023
0
    {
2024
0
      g_value_init (value, G_VALUE_TYPE (result));
2025
0
      g_value_copy (result, value);
2026
0
    }
2027
2028
0
  g_task_return_pointer (task, value, value_free);
2029
0
}
2030
2031
/**
2032
 * g_task_propagate_value:
2033
 * @task: a #GTask
2034
 * @value: (out caller-allocates): return location for the #GValue
2035
 * @error: return location for a #GError
2036
 *
2037
 * Gets the result of @task as a #GValue, and transfers ownership of
2038
 * that value to the caller. As with g_task_return_value(), this is
2039
 * a generic low-level method; g_task_propagate_pointer() and the like
2040
 * will usually be more useful for C code.
2041
 *
2042
 * If the task resulted in an error, or was cancelled, then this will
2043
 * instead set @error and return %FALSE.
2044
 *
2045
 * Since this method transfers ownership of the return value (or
2046
 * error) to the caller, you may only call it once.
2047
 *
2048
 * Returns: %TRUE if @task succeeded, %FALSE on error.
2049
 *
2050
 * Since: 2.64
2051
 */
2052
gboolean
2053
g_task_propagate_value (GTask   *task,
2054
                        GValue  *value,
2055
                        GError **error)
2056
0
{
2057
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2058
0
  g_return_val_if_fail (value != NULL, FALSE);
2059
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2060
2061
0
  if (g_task_propagate_error (task, error))
2062
0
    return FALSE;
2063
2064
0
  g_return_val_if_fail (task->result_set, FALSE);
2065
0
  g_return_val_if_fail (task->result_destroy == value_free, FALSE);
2066
2067
0
  memcpy (value, task->result.pointer, sizeof (GValue));
2068
0
  g_free (task->result.pointer);
2069
2070
0
  task->result_destroy = NULL;
2071
0
  task->result_set = FALSE;
2072
2073
0
  return TRUE;
2074
0
}
2075
2076
/**
2077
 * g_task_get_completed:
2078
 * @task: a #GTask.
2079
 *
2080
 * Gets the value of #GTask:completed. This changes from %FALSE to %TRUE after
2081
 * the task’s callback is invoked, and will return %FALSE if called from inside
2082
 * the callback.
2083
 *
2084
 * Returns: %TRUE if the task has completed, %FALSE otherwise.
2085
 *
2086
 * Since: 2.44
2087
 */
2088
gboolean
2089
g_task_get_completed (GTask *task)
2090
0
{
2091
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2092
2093
  /* Convert from a bit field to a boolean. */
2094
0
  return task->completed ? TRUE : FALSE;
2095
0
}
2096
2097
/**
2098
 * g_task_is_valid:
2099
 * @result: (type Gio.AsyncResult): A #GAsyncResult
2100
 * @source_object: (nullable) (type GObject): the source object
2101
 *   expected to be associated with the task
2102
 *
2103
 * Checks that @result is a #GTask, and that @source_object is its
2104
 * source object (or that @source_object is %NULL and @result has no
2105
 * source object). This can be used in g_return_if_fail() checks.
2106
 *
2107
 * Returns: %TRUE if @result and @source_object are valid, %FALSE
2108
 * if not
2109
 *
2110
 * Since: 2.36
2111
 */
2112
gboolean
2113
g_task_is_valid (gpointer result,
2114
                 gpointer source_object)
2115
0
{
2116
0
  if (!G_IS_TASK (result))
2117
0
    return FALSE;
2118
2119
0
  return G_TASK (result)->source_object == source_object;
2120
0
}
2121
2122
static gint
2123
g_task_compare_priority (gconstpointer a,
2124
                         gconstpointer b,
2125
                         gpointer      user_data)
2126
0
{
2127
0
  const GTask *ta = a;
2128
0
  const GTask *tb = b;
2129
0
  gboolean a_cancelled, b_cancelled;
2130
2131
  /* Tasks that are causing other tasks to block have higher
2132
   * priority.
2133
   */
2134
0
  if (ta->blocking_other_task && !tb->blocking_other_task)
2135
0
    return -1;
2136
0
  else if (tb->blocking_other_task && !ta->blocking_other_task)
2137
0
    return 1;
2138
2139
  /* Let already-cancelled tasks finish right away */
2140
0
  a_cancelled = (ta->check_cancellable &&
2141
0
                 g_cancellable_is_cancelled (ta->cancellable));
2142
0
  b_cancelled = (tb->check_cancellable &&
2143
0
                 g_cancellable_is_cancelled (tb->cancellable));
2144
0
  if (a_cancelled && !b_cancelled)
2145
0
    return -1;
2146
0
  else if (b_cancelled && !a_cancelled)
2147
0
    return 1;
2148
2149
  /* Lower priority == run sooner == negative return value */
2150
0
  return ta->priority - tb->priority;
2151
0
}
2152
2153
static gboolean
2154
trivial_source_dispatch (GSource     *source,
2155
                         GSourceFunc  callback,
2156
                         gpointer     user_data)
2157
0
{
2158
0
  return callback (user_data);
2159
0
}
2160
2161
GSourceFuncs trivial_source_funcs = {
2162
  NULL, /* prepare */
2163
  NULL, /* check */
2164
  trivial_source_dispatch,
2165
  NULL, /* finalize */
2166
  NULL, /* closure */
2167
  NULL  /* marshal */
2168
};
2169
2170
static void
2171
g_task_thread_pool_init (void)
2172
0
{
2173
0
  task_pool = g_thread_pool_new (g_task_thread_pool_thread, NULL,
2174
0
                                 G_TASK_POOL_SIZE, FALSE, NULL);
2175
0
  g_assert (task_pool != NULL);
2176
2177
0
  g_thread_pool_set_sort_function (task_pool, g_task_compare_priority, NULL);
2178
2179
0
  task_pool_manager = g_source_new (&trivial_source_funcs, sizeof (GSource));
2180
0
  g_source_set_name (task_pool_manager, "GTask thread pool manager");
2181
0
  g_source_set_callback (task_pool_manager, task_pool_manager_timeout, NULL, NULL);
2182
0
  g_source_set_ready_time (task_pool_manager, -1);
2183
0
  g_source_attach (task_pool_manager,
2184
0
                   GLIB_PRIVATE_CALL (g_get_worker_context ()));
2185
0
  g_source_unref (task_pool_manager);
2186
0
}
2187
2188
static void
2189
g_task_get_property (GObject    *object,
2190
                     guint       prop_id,
2191
                     GValue     *value,
2192
                     GParamSpec *pspec)
2193
0
{
2194
0
  GTask *task = G_TASK (object);
2195
2196
0
  switch ((GTaskProperty) prop_id)
2197
0
    {
2198
0
    case PROP_COMPLETED:
2199
0
      g_value_set_boolean (value, g_task_get_completed (task));
2200
0
      break;
2201
0
    }
2202
0
}
2203
2204
static void
2205
g_task_class_init (GTaskClass *klass)
2206
0
{
2207
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2208
2209
0
  gobject_class->get_property = g_task_get_property;
2210
0
  gobject_class->finalize = g_task_finalize;
2211
2212
  /**
2213
   * GTask:completed:
2214
   *
2215
   * Whether the task has completed, meaning its callback (if set) has been
2216
   * invoked. This can only happen after g_task_return_pointer(),
2217
   * g_task_return_error() or one of the other return functions have been called
2218
   * on the task.
2219
   *
2220
   * This property is guaranteed to change from %FALSE to %TRUE exactly once.
2221
   *
2222
   * The #GObject::notify signal for this change is emitted in the same main
2223
   * context as the task’s callback, immediately after that callback is invoked.
2224
   *
2225
   * Since: 2.44
2226
   */
2227
0
  g_object_class_install_property (gobject_class, PROP_COMPLETED,
2228
0
    g_param_spec_boolean ("completed",
2229
0
                          P_("Task completed"),
2230
0
                          P_("Whether the task has completed yet"),
2231
0
                          FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2232
2233
0
  if (G_UNLIKELY (task_pool_max_counter == 0))
2234
0
    {
2235
      /* We use two counters to track characteristics of the GTask thread pool.
2236
       * task pool max size - the value of g_thread_pool_set_max_threads()
2237
       * tasks running - the number of running threads
2238
       */
2239
0
      task_pool_max_counter = g_trace_define_int64_counter ("GIO", "task pool max size", "Maximum number of threads allowed in the GTask thread pool; see g_thread_pool_set_max_threads()");
2240
0
      tasks_running_counter = g_trace_define_int64_counter ("GIO", "tasks running", "Number of currently running tasks in the GTask thread pool");
2241
0
    }
2242
0
}
2243
2244
static gpointer
2245
g_task_get_user_data (GAsyncResult *res)
2246
0
{
2247
0
  return G_TASK (res)->callback_data;
2248
0
}
2249
2250
static gboolean
2251
g_task_is_tagged (GAsyncResult *res,
2252
                  gpointer      source_tag)
2253
0
{
2254
0
  return G_TASK (res)->source_tag == source_tag;
2255
0
}
2256
2257
static void
2258
g_task_async_result_iface_init (GAsyncResultIface *iface)
2259
0
{
2260
0
  iface->get_user_data = g_task_get_user_data;
2261
0
  iface->get_source_object = g_task_ref_source_object;
2262
0
  iface->is_tagged = g_task_is_tagged;
2263
0
}