Coverage Report

Created: 2025-06-13 06:20

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