Coverage Report

Created: 2025-07-11 06:47

/src/tinysparql/subprojects/glib-2.80.3/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 main
307
 * context (see [method@GLib.MainContext.push_thread_default]) where the `GTask`
308
 * 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
800
 * [thread-default main context][g-main-context-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. It is called automatically by
1130
 * g_task_set_source_tag() if not called already.
1131
 *
1132
 * Since: 2.60
1133
 */
1134
void
1135
(g_task_set_name) (GTask      *task,
1136
                   const char *name)
1137
0
{
1138
0
  char *new_name;
1139
1140
0
  g_return_if_fail (G_IS_TASK (task));
1141
1142
0
  new_name = g_strdup (name);
1143
0
  if (!task->name_is_static)
1144
0
    g_free (task->name);
1145
0
  task->name = g_steal_pointer (&new_name);
1146
0
  task->name_is_static = FALSE;
1147
0
}
1148
1149
/**
1150
 * g_task_set_static_name:
1151
 * @task: a #GTask
1152
 * @name: (nullable): a human readable name for the task. Must be a string literal
1153
 *
1154
 * Sets @task’s name, used in debugging and profiling.
1155
 *
1156
 * This is a variant of g_task_set_name() that avoids copying @name.
1157
 *
1158
 * Since: 2.76
1159
 */
1160
void
1161
g_task_set_static_name (GTask      *task,
1162
                        const char *name)
1163
0
{
1164
0
  g_return_if_fail (G_IS_TASK (task));
1165
1166
0
  if (!task->name_is_static)
1167
0
    g_free (task->name);
1168
0
  task->name = (char *) name;
1169
0
  task->name_is_static = TRUE;
1170
0
}
1171
1172
/**
1173
 * g_task_get_source_object:
1174
 * @task: a #GTask
1175
 *
1176
 * Gets the source object from @task. Like
1177
 * g_async_result_get_source_object(), but does not ref the object.
1178
 *
1179
 * Returns: (transfer none) (nullable) (type GObject): @task's source object, or %NULL
1180
 *
1181
 * Since: 2.36
1182
 */
1183
gpointer
1184
g_task_get_source_object (GTask *task)
1185
0
{
1186
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1187
1188
0
  return task->source_object;
1189
0
}
1190
1191
static GObject *
1192
g_task_ref_source_object (GAsyncResult *res)
1193
0
{
1194
0
  GTask *task = G_TASK (res);
1195
1196
0
  if (task->source_object)
1197
0
    return g_object_ref (task->source_object);
1198
0
  else
1199
0
    return NULL;
1200
0
}
1201
1202
/**
1203
 * g_task_get_task_data:
1204
 * @task: a #GTask
1205
 *
1206
 * Gets @task's `task_data`.
1207
 *
1208
 * Returns: (transfer none): @task's `task_data`.
1209
 *
1210
 * Since: 2.36
1211
 */
1212
gpointer
1213
g_task_get_task_data (GTask *task)
1214
0
{
1215
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1216
1217
0
  return task->task_data;
1218
0
}
1219
1220
/**
1221
 * g_task_get_priority:
1222
 * @task: a #GTask
1223
 *
1224
 * Gets @task's priority
1225
 *
1226
 * Returns: @task's priority
1227
 *
1228
 * Since: 2.36
1229
 */
1230
gint
1231
g_task_get_priority (GTask *task)
1232
0
{
1233
0
  g_return_val_if_fail (G_IS_TASK (task), G_PRIORITY_DEFAULT);
1234
1235
0
  return task->priority;
1236
0
}
1237
1238
/**
1239
 * g_task_get_context:
1240
 * @task: a #GTask
1241
 *
1242
 * Gets the #GMainContext that @task will return its result in (that
1243
 * is, the context that was the
1244
 * [thread-default main context][g-main-context-push-thread-default]
1245
 * at the point when @task was created).
1246
 *
1247
 * This will always return a non-%NULL value, even if the task's
1248
 * context is the default #GMainContext.
1249
 *
1250
 * Returns: (transfer none): @task's #GMainContext
1251
 *
1252
 * Since: 2.36
1253
 */
1254
GMainContext *
1255
g_task_get_context (GTask *task)
1256
0
{
1257
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1258
1259
0
  return task->context;
1260
0
}
1261
1262
/**
1263
 * g_task_get_cancellable:
1264
 * @task: a #GTask
1265
 *
1266
 * Gets @task's #GCancellable
1267
 *
1268
 * Returns: (nullable) (transfer none): @task's #GCancellable
1269
 *
1270
 * Since: 2.36
1271
 */
1272
GCancellable *
1273
g_task_get_cancellable (GTask *task)
1274
0
{
1275
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1276
1277
0
  return task->cancellable;
1278
0
}
1279
1280
/**
1281
 * g_task_get_check_cancellable:
1282
 * @task: the #GTask
1283
 *
1284
 * Gets @task's check-cancellable flag. See
1285
 * g_task_set_check_cancellable() for more details.
1286
 *
1287
 * Since: 2.36
1288
 */
1289
gboolean
1290
g_task_get_check_cancellable (GTask *task)
1291
0
{
1292
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1293
1294
  /* Convert from a bit field to a boolean. */
1295
0
  return task->check_cancellable ? TRUE : FALSE;
1296
0
}
1297
1298
/**
1299
 * g_task_get_return_on_cancel:
1300
 * @task: the #GTask
1301
 *
1302
 * Gets @task's return-on-cancel flag. See
1303
 * g_task_set_return_on_cancel() for more details.
1304
 *
1305
 * Since: 2.36
1306
 */
1307
gboolean
1308
g_task_get_return_on_cancel (GTask *task)
1309
0
{
1310
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
1311
1312
  /* Convert from a bit field to a boolean. */
1313
0
  return task->return_on_cancel ? TRUE : FALSE;
1314
0
}
1315
1316
/**
1317
 * g_task_get_source_tag:
1318
 * @task: a #GTask
1319
 *
1320
 * Gets @task's source tag. See g_task_set_source_tag().
1321
 *
1322
 * Returns: (transfer none): @task's source tag
1323
 *
1324
 * Since: 2.36
1325
 */
1326
gpointer
1327
g_task_get_source_tag (GTask *task)
1328
0
{
1329
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1330
1331
0
  return task->source_tag;
1332
0
}
1333
1334
/**
1335
 * g_task_get_name:
1336
 * @task: a #GTask
1337
 *
1338
 * Gets @task’s name. See g_task_set_name().
1339
 *
1340
 * Returns: (nullable) (transfer none): @task’s name, or %NULL
1341
 * Since: 2.60
1342
 */
1343
const gchar *
1344
g_task_get_name (GTask *task)
1345
0
{
1346
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1347
1348
0
  return task->name;
1349
0
}
1350
1351
static void
1352
g_task_return_now (GTask *task)
1353
0
{
1354
0
  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object, task->callback,
1355
0
                                 task->callback_data));
1356
1357
0
  g_main_context_push_thread_default (task->context);
1358
1359
0
  if (task->callback != NULL)
1360
0
    {
1361
0
      task->callback (task->source_object,
1362
0
                      G_ASYNC_RESULT (task),
1363
0
                      task->callback_data);
1364
0
    }
1365
1366
0
  task->completed = TRUE;
1367
0
  g_object_notify (G_OBJECT (task), "completed");
1368
1369
0
  g_main_context_pop_thread_default (task->context);
1370
0
}
1371
1372
static gboolean
1373
complete_in_idle_cb (gpointer task)
1374
0
{
1375
0
  g_task_return_now (task);
1376
0
  g_object_unref (task);
1377
0
  return FALSE;
1378
0
}
1379
1380
typedef enum {
1381
  G_TASK_RETURN_SUCCESS,
1382
  G_TASK_RETURN_ERROR,
1383
  G_TASK_RETURN_FROM_THREAD
1384
} GTaskReturnType;
1385
1386
static void
1387
g_task_return (GTask           *task,
1388
               GTaskReturnType  type)
1389
0
{
1390
0
  GSource *source;
1391
1392
0
  if (type != G_TASK_RETURN_FROM_THREAD)
1393
0
    task->ever_returned = TRUE;
1394
1395
0
  if (type == G_TASK_RETURN_SUCCESS)
1396
0
    task->result_set = TRUE;
1397
1398
0
  if (task->synchronous)
1399
0
    return;
1400
1401
  /* Normally we want to invoke the task's callback when its return
1402
   * value is set. But if the task is running in a thread, then we
1403
   * want to wait until after the task_func returns, to simplify
1404
   * locking/refcounting/etc.
1405
   */
1406
0
  if (G_TASK_IS_THREADED (task) && type != G_TASK_RETURN_FROM_THREAD)
1407
0
    return;
1408
1409
0
  g_object_ref (task);
1410
1411
  /* See if we can complete the task immediately. First, we have to be
1412
   * running inside the task's thread/GMainContext.
1413
   */
1414
0
  source = g_main_current_source ();
1415
0
  if (source && g_source_get_context (source) == task->context)
1416
0
    {
1417
      /* Second, we can only complete immediately if this is not the
1418
       * same iteration of the main loop that the task was created in.
1419
       */
1420
0
      if (g_source_get_time (source) > task->creation_time)
1421
0
        {
1422
          /* Finally, if the task has been cancelled, we shouldn't
1423
           * return synchronously from inside the
1424
           * GCancellable::cancelled handler. It's easier to run
1425
           * another iteration of the main loop than tracking how the
1426
           * cancellation was handled.
1427
           */
1428
0
          if (!g_cancellable_is_cancelled (task->cancellable))
1429
0
            {
1430
0
              g_task_return_now (task);
1431
0
              g_object_unref (task);
1432
0
              return;
1433
0
            }
1434
0
        }
1435
0
    }
1436
1437
  /* Otherwise, complete in the next iteration */
1438
0
  source = g_idle_source_new ();
1439
1440
  /* Note: in case the task name is NULL we set it as a const string instead
1441
   * of going through the concat path which is more expensive and may show in the
1442
   * profiler if g_task_return is called very often
1443
   */
1444
0
  if (task->name == NULL)
1445
0
    g_source_set_static_name (source, "[gio] (unnamed) complete_in_idle_cb");
1446
0
  else
1447
0
    {
1448
0
      gchar *source_name;
1449
1450
0
      source_name = g_strconcat ("[gio] ", task->name, " complete_in_idle_cb", NULL);
1451
0
      g_source_set_name (source, source_name);
1452
0
      g_free (source_name);
1453
0
    }
1454
1455
0
  g_task_attach_source (task, source, complete_in_idle_cb);
1456
0
  g_source_unref (source);
1457
0
}
1458
1459
1460
/**
1461
 * GTaskThreadFunc:
1462
 * @task: the #GTask
1463
 * @source_object: (type GObject): @task's source object
1464
 * @task_data: @task's task data
1465
 * @cancellable: @task's #GCancellable, or %NULL
1466
 *
1467
 * The prototype for a task function to be run in a thread via
1468
 * g_task_run_in_thread() or g_task_run_in_thread_sync().
1469
 *
1470
 * If the return-on-cancel flag is set on @task, and @cancellable gets
1471
 * cancelled, then the #GTask will be completed immediately (as though
1472
 * g_task_return_error_if_cancelled() had been called), without
1473
 * waiting for the task function to complete. However, the task
1474
 * function will continue running in its thread in the background. The
1475
 * function therefore needs to be careful about how it uses
1476
 * externally-visible state in this case. See
1477
 * g_task_set_return_on_cancel() for more details.
1478
 *
1479
 * Other than in that case, @task will be completed when the
1480
 * #GTaskThreadFunc returns, not when it calls a
1481
 * `g_task_return_` function.
1482
 *
1483
 * Since: 2.36
1484
 */
1485
1486
static void task_thread_cancelled (GCancellable *cancellable,
1487
                                   gpointer      user_data);
1488
1489
static void
1490
g_task_thread_complete (GTask *task)
1491
0
{
1492
0
  g_mutex_lock (&task->lock);
1493
0
  if (task->thread_complete)
1494
0
    {
1495
      /* The task belatedly completed after having been cancelled
1496
       * (or was cancelled in the midst of being completed).
1497
       */
1498
0
      g_mutex_unlock (&task->lock);
1499
0
      return;
1500
0
    }
1501
1502
0
  TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
1503
1504
0
  task->thread_complete = TRUE;
1505
0
  g_mutex_unlock (&task->lock);
1506
1507
0
  if (task->cancellable)
1508
0
    g_signal_handlers_disconnect_by_func (task->cancellable, task_thread_cancelled, task);
1509
1510
0
  if (task->synchronous)
1511
0
    g_cond_signal (&task->cond);
1512
0
  else
1513
0
    g_task_return (task, G_TASK_RETURN_FROM_THREAD);
1514
0
}
1515
1516
static gboolean
1517
task_pool_manager_timeout (gpointer user_data)
1518
0
{
1519
0
  g_mutex_lock (&task_pool_mutex);
1520
0
  g_thread_pool_set_max_threads (task_pool, tasks_running + 1, NULL);
1521
0
  g_trace_set_int64_counter (task_pool_max_counter, tasks_running + 1);
1522
0
  g_source_set_ready_time (task_pool_manager, -1);
1523
0
  g_mutex_unlock (&task_pool_mutex);
1524
1525
0
  return TRUE;
1526
0
}
1527
1528
static void
1529
g_task_thread_setup (void)
1530
0
{
1531
0
  g_private_set (&task_private, GUINT_TO_POINTER (TRUE));
1532
0
  g_mutex_lock (&task_pool_mutex);
1533
0
  tasks_running++;
1534
1535
0
  g_trace_set_int64_counter (tasks_running_counter, tasks_running);
1536
1537
0
  if (tasks_running == G_TASK_POOL_SIZE)
1538
0
    task_wait_time = G_TASK_WAIT_TIME_BASE;
1539
0
  else if (tasks_running > G_TASK_POOL_SIZE && tasks_running < G_TASK_WAIT_TIME_MAX_POOL_SIZE)
1540
0
    task_wait_time *= G_TASK_WAIT_TIME_MULTIPLIER;
1541
1542
0
  if (tasks_running >= G_TASK_POOL_SIZE)
1543
0
    g_source_set_ready_time (task_pool_manager, g_get_monotonic_time () + task_wait_time);
1544
1545
0
  g_mutex_unlock (&task_pool_mutex);
1546
0
}
1547
1548
static void
1549
g_task_thread_cleanup (void)
1550
0
{
1551
0
  gint tasks_pending;
1552
1553
0
  g_mutex_lock (&task_pool_mutex);
1554
0
  tasks_pending = g_thread_pool_unprocessed (task_pool);
1555
1556
0
  if (tasks_running > G_TASK_POOL_SIZE)
1557
0
    {
1558
0
      g_thread_pool_set_max_threads (task_pool, tasks_running - 1, NULL);
1559
0
      g_trace_set_int64_counter (task_pool_max_counter, tasks_running - 1);
1560
0
    }
1561
0
  else if (tasks_running + tasks_pending < G_TASK_POOL_SIZE)
1562
0
    g_source_set_ready_time (task_pool_manager, -1);
1563
1564
0
  if (tasks_running > G_TASK_POOL_SIZE && tasks_running < G_TASK_WAIT_TIME_MAX_POOL_SIZE)
1565
0
    task_wait_time /= G_TASK_WAIT_TIME_MULTIPLIER;
1566
1567
0
  tasks_running--;
1568
1569
0
  g_trace_set_int64_counter (tasks_running_counter, tasks_running);
1570
1571
0
  g_mutex_unlock (&task_pool_mutex);
1572
0
  g_private_set (&task_private, GUINT_TO_POINTER (FALSE));
1573
0
}
1574
1575
static void
1576
g_task_thread_pool_thread (gpointer thread_data,
1577
                           gpointer pool_data)
1578
0
{
1579
0
  GTask *task = thread_data;
1580
1581
0
  g_task_thread_setup ();
1582
1583
0
  task->task_func (task, task->source_object, task->task_data,
1584
0
                   task->cancellable);
1585
0
  g_task_thread_complete (task);
1586
0
  g_object_unref (task);
1587
1588
0
  g_task_thread_cleanup ();
1589
0
}
1590
1591
static void
1592
task_thread_cancelled (GCancellable *cancellable,
1593
                       gpointer      user_data)
1594
0
{
1595
0
  GTask *task = user_data;
1596
1597
  /* Move this task to the front of the queue - no need for
1598
   * a complete resorting of the queue.
1599
   */
1600
0
  g_thread_pool_move_to_front (task_pool, task);
1601
1602
0
  g_mutex_lock (&task->lock);
1603
0
  task->thread_cancelled = TRUE;
1604
1605
0
  if (!task->return_on_cancel)
1606
0
    {
1607
0
      g_mutex_unlock (&task->lock);
1608
0
      return;
1609
0
    }
1610
1611
  /* We don't actually set task->error; g_task_return_error() doesn't
1612
   * use a lock, and g_task_propagate_error() will call
1613
   * g_cancellable_set_error_if_cancelled() anyway.
1614
   */
1615
0
  g_mutex_unlock (&task->lock);
1616
0
  g_task_thread_complete (task);
1617
0
}
1618
1619
static void
1620
task_thread_cancelled_disconnect_notify (gpointer  task,
1621
                                         GClosure *closure)
1622
0
{
1623
0
  g_object_unref (task);
1624
0
}
1625
1626
static void
1627
g_task_start_task_thread (GTask           *task,
1628
                          GTaskThreadFunc  task_func)
1629
0
{
1630
0
  g_mutex_init (&task->lock);
1631
0
  g_cond_init (&task->cond);
1632
1633
0
  g_mutex_lock (&task->lock);
1634
1635
0
  TRACE (GIO_TASK_BEFORE_RUN_IN_THREAD (task, task_func));
1636
1637
0
  task->task_func = task_func;
1638
1639
0
  if (task->cancellable)
1640
0
    {
1641
0
      if (task->return_on_cancel &&
1642
0
          g_cancellable_set_error_if_cancelled (task->cancellable,
1643
0
                                                &task->error))
1644
0
        {
1645
0
          task->thread_cancelled = task->thread_complete = TRUE;
1646
0
          TRACE (GIO_TASK_AFTER_RUN_IN_THREAD (task, task->thread_cancelled));
1647
0
          g_thread_pool_push (task_pool, g_object_ref (task), NULL);
1648
0
          return;
1649
0
        }
1650
1651
      /* This introduces a reference count loop between the GTask and
1652
       * GCancellable, but is necessary to avoid a race on finalising the GTask
1653
       * between task_thread_cancelled() (in one thread) and
1654
       * g_task_thread_complete() (in another).
1655
       *
1656
       * Accordingly, the signal handler *must* be removed once the task has
1657
       * completed.
1658
       */
1659
0
      g_signal_connect_data (task->cancellable, "cancelled",
1660
0
                             G_CALLBACK (task_thread_cancelled),
1661
0
                             g_object_ref (task),
1662
0
                             task_thread_cancelled_disconnect_notify,
1663
0
                             G_CONNECT_DEFAULT);
1664
0
    }
1665
1666
0
  if (g_private_get (&task_private))
1667
0
    task->blocking_other_task = TRUE;
1668
0
  g_thread_pool_push (task_pool, g_object_ref (task), NULL);
1669
0
}
1670
1671
/**
1672
 * g_task_run_in_thread:
1673
 * @task: a #GTask
1674
 * @task_func: (scope async): a #GTaskThreadFunc
1675
 *
1676
 * Runs @task_func in another thread. When @task_func returns, @task's
1677
 * #GAsyncReadyCallback will be invoked in @task's #GMainContext.
1678
 *
1679
 * This takes a ref on @task until the task completes.
1680
 *
1681
 * See #GTaskThreadFunc for more details about how @task_func is handled.
1682
 *
1683
 * Although GLib currently rate-limits the tasks queued via
1684
 * g_task_run_in_thread(), you should not assume that it will always
1685
 * do this. If you have a very large number of tasks to run (several tens of
1686
 * tasks), but don't want them to all run at once, you should only queue a
1687
 * limited number of them (around ten) at a time.
1688
 *
1689
 * Be aware that if your task depends on other tasks to complete, use of this
1690
 * function could lead to a livelock if the other tasks also use this function
1691
 * and enough of them (around 10) execute in a dependency chain, as that will
1692
 * exhaust the thread pool. If this situation is possible, consider using a
1693
 * separate worker thread or thread pool explicitly, rather than using
1694
 * g_task_run_in_thread().
1695
 *
1696
 * Since: 2.36
1697
 */
1698
void
1699
g_task_run_in_thread (GTask           *task,
1700
                      GTaskThreadFunc  task_func)
1701
0
{
1702
0
  g_return_if_fail (G_IS_TASK (task));
1703
1704
0
  g_object_ref (task);
1705
0
  g_task_start_task_thread (task, task_func);
1706
1707
  /* The task may already be cancelled, or g_thread_pool_push() may
1708
   * have failed.
1709
   */
1710
0
  if (task->thread_complete)
1711
0
    {
1712
0
      g_mutex_unlock (&task->lock);
1713
0
      g_task_return (task, G_TASK_RETURN_FROM_THREAD);
1714
0
    }
1715
0
  else
1716
0
    g_mutex_unlock (&task->lock);
1717
1718
0
  g_object_unref (task);
1719
0
}
1720
1721
/**
1722
 * g_task_run_in_thread_sync:
1723
 * @task: a #GTask
1724
 * @task_func: (scope async): a #GTaskThreadFunc
1725
 *
1726
 * Runs @task_func in another thread, and waits for it to return or be
1727
 * cancelled. You can use g_task_propagate_pointer(), etc, afterward
1728
 * to get the result of @task_func.
1729
 *
1730
 * See #GTaskThreadFunc for more details about how @task_func is handled.
1731
 *
1732
 * Normally this is used with tasks created with a %NULL
1733
 * `callback`, but note that even if the task does
1734
 * have a callback, it will not be invoked when @task_func returns.
1735
 * #GTask:completed will be set to %TRUE just before this function returns.
1736
 *
1737
 * Although GLib currently rate-limits the tasks queued via
1738
 * g_task_run_in_thread_sync(), you should not assume that it will
1739
 * always do this. If you have a very large number of tasks to run,
1740
 * but don't want them to all run at once, you should only queue a
1741
 * limited number of them at a time.
1742
 *
1743
 * Since: 2.36
1744
 */
1745
void
1746
g_task_run_in_thread_sync (GTask           *task,
1747
                           GTaskThreadFunc  task_func)
1748
0
{
1749
0
  g_return_if_fail (G_IS_TASK (task));
1750
1751
0
  g_object_ref (task);
1752
1753
0
  task->synchronous = TRUE;
1754
0
  g_task_start_task_thread (task, task_func);
1755
1756
0
  while (!task->thread_complete)
1757
0
    g_cond_wait (&task->cond, &task->lock);
1758
1759
0
  g_mutex_unlock (&task->lock);
1760
1761
0
  TRACE (GIO_TASK_BEFORE_RETURN (task, task->source_object,
1762
0
                                 NULL  /* callback */,
1763
0
                                 NULL  /* callback data */));
1764
1765
  /* Notify of completion in this thread. */
1766
0
  task->completed = TRUE;
1767
0
  g_object_notify (G_OBJECT (task), "completed");
1768
1769
0
  g_object_unref (task);
1770
0
}
1771
1772
/**
1773
 * g_task_attach_source:
1774
 * @task: a #GTask
1775
 * @source: the source to attach
1776
 * @callback: the callback to invoke when @source triggers
1777
 *
1778
 * A utility function for dealing with async operations where you need
1779
 * to wait for a #GSource to trigger. Attaches @source to @task's
1780
 * #GMainContext with @task's [priority](iface.AsyncResult.html#io-priority),
1781
 * and sets @source's callback to @callback, with @task as the callback's
1782
 * `user_data`.
1783
 *
1784
 * It will set the @source’s name to the task’s name (as set with
1785
 * g_task_set_name()), if one has been set on the task and the source doesn’t
1786
 * yet have a name.
1787
 *
1788
 * This takes a reference on @task until @source is destroyed.
1789
 *
1790
 * Since: 2.36
1791
 */
1792
void
1793
g_task_attach_source (GTask       *task,
1794
                      GSource     *source,
1795
                      GSourceFunc  callback)
1796
0
{
1797
0
  g_return_if_fail (G_IS_TASK (task));
1798
1799
0
  g_source_set_callback (source, callback,
1800
0
                         g_object_ref (task), g_object_unref);
1801
0
  g_source_set_priority (source, task->priority);
1802
0
  if (task->name != NULL && g_source_get_name (source) == NULL)
1803
0
    g_source_set_name (source, task->name);
1804
1805
0
  g_source_attach (source, task->context);
1806
0
}
1807
1808
1809
static gboolean
1810
g_task_propagate_error (GTask   *task,
1811
                        GError **error)
1812
0
{
1813
0
  gboolean error_set;
1814
1815
0
  if (task->check_cancellable &&
1816
0
      g_cancellable_set_error_if_cancelled (task->cancellable, error))
1817
0
    error_set = TRUE;
1818
0
  else if (task->error)
1819
0
    {
1820
0
      g_propagate_error (error, task->error);
1821
0
      task->error = NULL;
1822
0
      task->had_error = TRUE;
1823
0
      error_set = TRUE;
1824
0
    }
1825
0
  else
1826
0
    error_set = FALSE;
1827
1828
0
  TRACE (GIO_TASK_PROPAGATE (task, error_set));
1829
1830
0
  return error_set;
1831
0
}
1832
1833
/**
1834
 * g_task_return_pointer:
1835
 * @task: a #GTask
1836
 * @result: (nullable) (transfer full): the pointer result of a task
1837
 *     function
1838
 * @result_destroy: (nullable): a #GDestroyNotify function.
1839
 *
1840
 * Sets @task's result to @result and completes the task. If @result
1841
 * is not %NULL, then @result_destroy will be used to free @result if
1842
 * the caller does not take ownership of it with
1843
 * g_task_propagate_pointer().
1844
 *
1845
 * "Completes the task" means that for an ordinary asynchronous task
1846
 * it will either invoke the task's callback, or else queue that
1847
 * callback to be invoked in the proper #GMainContext, or in the next
1848
 * iteration of the current #GMainContext. For a task run via
1849
 * g_task_run_in_thread() or g_task_run_in_thread_sync(), calling this
1850
 * method will save @result to be returned to the caller later, but
1851
 * the task will not actually be completed until the #GTaskThreadFunc
1852
 * exits.
1853
 *
1854
 * Note that since the task may be completed before returning from
1855
 * g_task_return_pointer(), you cannot assume that @result is still
1856
 * valid after calling this, unless you are still holding another
1857
 * reference on it.
1858
 *
1859
 * Since: 2.36
1860
 */
1861
void
1862
g_task_return_pointer (GTask          *task,
1863
                       gpointer        result,
1864
                       GDestroyNotify  result_destroy)
1865
0
{
1866
0
  g_return_if_fail (G_IS_TASK (task));
1867
0
  g_return_if_fail (!task->ever_returned);
1868
1869
0
  task->result.pointer = result;
1870
0
  task->result_destroy = result_destroy;
1871
1872
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1873
0
}
1874
1875
/**
1876
 * g_task_propagate_pointer:
1877
 * @task: a #GTask
1878
 * @error: return location for a #GError
1879
 *
1880
 * Gets the result of @task as a pointer, and transfers ownership
1881
 * of that value to the caller.
1882
 *
1883
 * If the task resulted in an error, or was cancelled, then this will
1884
 * instead return %NULL and set @error.
1885
 *
1886
 * Since this method transfers ownership of the return value (or
1887
 * error) to the caller, you may only call it once.
1888
 *
1889
 * Returns: (transfer full): the task result, or %NULL on error
1890
 *
1891
 * Since: 2.36
1892
 */
1893
gpointer
1894
g_task_propagate_pointer (GTask   *task,
1895
                          GError **error)
1896
0
{
1897
0
  g_return_val_if_fail (G_IS_TASK (task), NULL);
1898
1899
0
  if (g_task_propagate_error (task, error))
1900
0
    return NULL;
1901
1902
0
  g_return_val_if_fail (task->result_set, NULL);
1903
1904
0
  task->result_destroy = NULL;
1905
0
  task->result_set = FALSE;
1906
0
  return task->result.pointer;
1907
0
}
1908
1909
/**
1910
 * g_task_return_int:
1911
 * @task: a #GTask.
1912
 * @result: the integer (#gssize) result of a task function.
1913
 *
1914
 * Sets @task's result to @result and completes the task (see
1915
 * g_task_return_pointer() for more discussion of exactly what this
1916
 * means).
1917
 *
1918
 * Since: 2.36
1919
 */
1920
void
1921
g_task_return_int (GTask  *task,
1922
                   gssize  result)
1923
0
{
1924
0
  g_return_if_fail (G_IS_TASK (task));
1925
0
  g_return_if_fail (!task->ever_returned);
1926
1927
0
  task->result.size = result;
1928
1929
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1930
0
}
1931
1932
/**
1933
 * g_task_propagate_int:
1934
 * @task: a #GTask.
1935
 * @error: return location for a #GError
1936
 *
1937
 * Gets the result of @task as an integer (#gssize).
1938
 *
1939
 * If the task resulted in an error, or was cancelled, then this will
1940
 * instead return -1 and set @error.
1941
 *
1942
 * Since this method transfers ownership of the return value (or
1943
 * error) to the caller, you may only call it once.
1944
 *
1945
 * Returns: the task result, or -1 on error
1946
 *
1947
 * Since: 2.36
1948
 */
1949
gssize
1950
g_task_propagate_int (GTask   *task,
1951
                      GError **error)
1952
0
{
1953
0
  g_return_val_if_fail (G_IS_TASK (task), -1);
1954
1955
0
  if (g_task_propagate_error (task, error))
1956
0
    return -1;
1957
1958
0
  g_return_val_if_fail (task->result_set, -1);
1959
1960
0
  task->result_set = FALSE;
1961
0
  return task->result.size;
1962
0
}
1963
1964
/**
1965
 * g_task_return_boolean:
1966
 * @task: a #GTask.
1967
 * @result: the #gboolean result of a task function.
1968
 *
1969
 * Sets @task's result to @result and completes the task (see
1970
 * g_task_return_pointer() for more discussion of exactly what this
1971
 * means).
1972
 *
1973
 * Since: 2.36
1974
 */
1975
void
1976
g_task_return_boolean (GTask    *task,
1977
                       gboolean  result)
1978
0
{
1979
0
  g_return_if_fail (G_IS_TASK (task));
1980
0
  g_return_if_fail (!task->ever_returned);
1981
1982
0
  task->result.boolean = result;
1983
1984
0
  g_task_return (task, G_TASK_RETURN_SUCCESS);
1985
0
}
1986
1987
/**
1988
 * g_task_propagate_boolean:
1989
 * @task: a #GTask.
1990
 * @error: return location for a #GError
1991
 *
1992
 * Gets the result of @task as a #gboolean.
1993
 *
1994
 * If the task resulted in an error, or was cancelled, then this will
1995
 * instead return %FALSE and set @error.
1996
 *
1997
 * Since this method transfers ownership of the return value (or
1998
 * error) to the caller, you may only call it once.
1999
 *
2000
 * Returns: the task result, or %FALSE on error
2001
 *
2002
 * Since: 2.36
2003
 */
2004
gboolean
2005
g_task_propagate_boolean (GTask   *task,
2006
                          GError **error)
2007
0
{
2008
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2009
2010
0
  if (g_task_propagate_error (task, error))
2011
0
    return FALSE;
2012
2013
0
  g_return_val_if_fail (task->result_set, FALSE);
2014
2015
0
  task->result_set = FALSE;
2016
0
  return task->result.boolean;
2017
0
}
2018
2019
/**
2020
 * g_task_return_error:
2021
 * @task: a #GTask.
2022
 * @error: (transfer full): the #GError result of a task function.
2023
 *
2024
 * Sets @task's result to @error (which @task assumes ownership of)
2025
 * and completes the task (see g_task_return_pointer() for more
2026
 * discussion of exactly what this means).
2027
 *
2028
 * Note that since the task takes ownership of @error, and since the
2029
 * task may be completed before returning from g_task_return_error(),
2030
 * you cannot assume that @error is still valid after calling this.
2031
 * Call g_error_copy() on the error if you need to keep a local copy
2032
 * as well.
2033
 *
2034
 * See also [method@Gio.Task.return_new_error],
2035
 * [method@Gio.Task.return_new_error_literal].
2036
 *
2037
 * Since: 2.36
2038
 */
2039
void
2040
g_task_return_error (GTask  *task,
2041
                     GError *error)
2042
0
{
2043
0
  g_return_if_fail (G_IS_TASK (task));
2044
0
  g_return_if_fail (!task->ever_returned);
2045
0
  g_return_if_fail (error != NULL);
2046
2047
0
  task->error = error;
2048
2049
0
  g_task_return (task, G_TASK_RETURN_ERROR);
2050
0
}
2051
2052
/**
2053
 * g_task_return_prefixed_error:
2054
 * @task: a #GTask.
2055
 * @error: (transfer full): the #GError result of a task function.
2056
 * @format: a string with format characters.
2057
 * @...: a list of values to insert into @format.
2058
 * 
2059
 * Sets @task's result to @error (which @task assumes ownership of), with
2060
 * the message prefixed according to @format, and completes the task
2061
 * (see g_task_return_pointer() for more discussion of exactly what this
2062
 * means).
2063
 *
2064
 * Note that since the task takes ownership of @error, and since the
2065
 * task may be completed before returning from g_task_return_prefixed_error(),
2066
 * you cannot assume that @error is still valid after calling this.
2067
 * Call g_error_copy() on the error if you need to keep a local copy
2068
 * as well.
2069
 *
2070
 * See also g_task_return_error(), g_prefix_error().
2071
 *
2072
 * Since: 2.80
2073
 */
2074
void
2075
g_task_return_prefixed_error (GTask      *task,
2076
                              GError     *error,
2077
                              const char *format,
2078
                              ...)
2079
0
{
2080
0
  char *prefix;
2081
0
  va_list ap;
2082
2083
0
  g_return_if_fail (G_IS_TASK (task));
2084
0
  g_return_if_fail (!task->ever_returned);
2085
0
  g_return_if_fail (error != NULL);
2086
2087
0
  task->error = error;
2088
2089
0
  va_start (ap, format);
2090
0
  prefix = g_strdup_vprintf (format, ap);
2091
0
  va_end (ap);
2092
2093
0
  g_prefix_error_literal (&task->error, prefix);
2094
2095
0
  g_free (prefix);
2096
2097
0
  g_task_return (task, G_TASK_RETURN_ERROR);
2098
0
}
2099
2100
/**
2101
 * g_task_return_new_error:
2102
 * @task: a #GTask.
2103
 * @domain: a #GQuark.
2104
 * @code: an error code.
2105
 * @format: a string with format characters.
2106
 * @...: a list of values to insert into @format.
2107
 *
2108
 * Sets @task's result to a new #GError created from @domain, @code,
2109
 * @format, and the remaining arguments, and completes the task (see
2110
 * g_task_return_pointer() for more discussion of exactly what this
2111
 * means).
2112
 *
2113
 * See also g_task_return_error().
2114
 *
2115
 * Since: 2.36
2116
 */
2117
void
2118
g_task_return_new_error (GTask           *task,
2119
                         GQuark           domain,
2120
                         gint             code,
2121
                         const char      *format,
2122
                         ...)
2123
0
{
2124
0
  GError *error;
2125
0
  va_list args;
2126
2127
0
  va_start (args, format);
2128
0
  error = g_error_new_valist (domain, code, format, args);
2129
0
  va_end (args);
2130
2131
0
  g_task_return_error (task, error);
2132
0
}
2133
2134
/**
2135
 * g_task_return_new_error_literal:
2136
 * @task: a #GTask.
2137
 * @domain: a #GQuark.
2138
 * @code: an error code.
2139
 * @message: an error message
2140
 *
2141
 * Sets @task’s result to a new [type@GLib.Error] created from @domain, @code,
2142
 * @message and completes the task.
2143
 *
2144
 * See [method@Gio.Task.return_pointer] for more discussion of exactly what
2145
 * ‘completing the task’ means.
2146
 *
2147
 * See also [method@Gio.Task.return_new_error].
2148
 *
2149
 * Since: 2.80
2150
 */
2151
void
2152
g_task_return_new_error_literal (GTask      *task,
2153
                                 GQuark      domain,
2154
                                 gint        code,
2155
                                 const char *message)
2156
0
{
2157
0
  g_task_return_error (task, g_error_new_literal (domain, code, message));
2158
0
}
2159
2160
/**
2161
 * g_task_return_error_if_cancelled:
2162
 * @task: a #GTask
2163
 *
2164
 * Checks if @task's #GCancellable has been cancelled, and if so, sets
2165
 * @task's error accordingly and completes the task (see
2166
 * g_task_return_pointer() for more discussion of exactly what this
2167
 * means).
2168
 *
2169
 * Returns: %TRUE if @task has been cancelled, %FALSE if not
2170
 *
2171
 * Since: 2.36
2172
 */
2173
gboolean
2174
g_task_return_error_if_cancelled (GTask *task)
2175
0
{
2176
0
  GError *error = NULL;
2177
2178
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2179
0
  g_return_val_if_fail (!task->ever_returned, FALSE);
2180
2181
0
  if (g_cancellable_set_error_if_cancelled (task->cancellable, &error))
2182
0
    {
2183
      /* We explicitly set task->error so this works even when
2184
       * check-cancellable is not set.
2185
       */
2186
0
      g_clear_error (&task->error);
2187
0
      task->error = error;
2188
2189
0
      g_task_return (task, G_TASK_RETURN_ERROR);
2190
0
      return TRUE;
2191
0
    }
2192
0
  else
2193
0
    return FALSE;
2194
0
}
2195
2196
/**
2197
 * g_task_had_error:
2198
 * @task: a #GTask.
2199
 *
2200
 * Tests if @task resulted in an error.
2201
 *
2202
 * Returns: %TRUE if the task resulted in an error, %FALSE otherwise.
2203
 *
2204
 * Since: 2.36
2205
 */
2206
gboolean
2207
g_task_had_error (GTask *task)
2208
0
{
2209
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2210
2211
0
  if (task->error != NULL || task->had_error)
2212
0
    return TRUE;
2213
2214
0
  if (task->check_cancellable && g_cancellable_is_cancelled (task->cancellable))
2215
0
    return TRUE;
2216
2217
0
  return FALSE;
2218
0
}
2219
2220
static void
2221
value_free (gpointer value)
2222
0
{
2223
0
  g_value_unset (value);
2224
0
  g_free (value);
2225
0
}
2226
2227
/**
2228
 * g_task_return_value:
2229
 * @task: a #GTask
2230
 * @result: (nullable) (transfer none): the #GValue result of
2231
 *                                      a task function
2232
 *
2233
 * Sets @task's result to @result (by copying it) and completes the task.
2234
 *
2235
 * If @result is %NULL then a #GValue of type %G_TYPE_POINTER
2236
 * with a value of %NULL will be used for the result.
2237
 *
2238
 * This is a very generic low-level method intended primarily for use
2239
 * by language bindings; for C code, g_task_return_pointer() and the
2240
 * like will normally be much easier to use.
2241
 *
2242
 * Since: 2.64
2243
 */
2244
void
2245
g_task_return_value (GTask  *task,
2246
                     GValue *result)
2247
0
{
2248
0
  GValue *value;
2249
2250
0
  g_return_if_fail (G_IS_TASK (task));
2251
0
  g_return_if_fail (!task->ever_returned);
2252
2253
0
  value = g_new0 (GValue, 1);
2254
2255
0
  if (result == NULL)
2256
0
    {
2257
0
      g_value_init (value, G_TYPE_POINTER);
2258
0
      g_value_set_pointer (value, NULL);
2259
0
    }
2260
0
  else
2261
0
    {
2262
0
      g_value_init (value, G_VALUE_TYPE (result));
2263
0
      g_value_copy (result, value);
2264
0
    }
2265
2266
0
  g_task_return_pointer (task, value, value_free);
2267
0
}
2268
2269
/**
2270
 * g_task_propagate_value:
2271
 * @task: a #GTask
2272
 * @value: (out caller-allocates): return location for the #GValue
2273
 * @error: return location for a #GError
2274
 *
2275
 * Gets the result of @task as a #GValue, and transfers ownership of
2276
 * that value to the caller. As with g_task_return_value(), this is
2277
 * a generic low-level method; g_task_propagate_pointer() and the like
2278
 * will usually be more useful for C code.
2279
 *
2280
 * If the task resulted in an error, or was cancelled, then this will
2281
 * instead set @error and return %FALSE.
2282
 *
2283
 * Since this method transfers ownership of the return value (or
2284
 * error) to the caller, you may only call it once.
2285
 *
2286
 * Returns: %TRUE if @task succeeded, %FALSE on error.
2287
 *
2288
 * Since: 2.64
2289
 */
2290
gboolean
2291
g_task_propagate_value (GTask   *task,
2292
                        GValue  *value,
2293
                        GError **error)
2294
0
{
2295
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2296
0
  g_return_val_if_fail (value != NULL, FALSE);
2297
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2298
2299
0
  if (g_task_propagate_error (task, error))
2300
0
    return FALSE;
2301
2302
0
  g_return_val_if_fail (task->result_set, FALSE);
2303
0
  g_return_val_if_fail (task->result_destroy == value_free, FALSE);
2304
2305
0
  memcpy (value, task->result.pointer, sizeof (GValue));
2306
0
  g_free (task->result.pointer);
2307
2308
0
  task->result_destroy = NULL;
2309
0
  task->result_set = FALSE;
2310
2311
0
  return TRUE;
2312
0
}
2313
2314
/**
2315
 * g_task_get_completed:
2316
 * @task: a #GTask.
2317
 *
2318
 * Gets the value of #GTask:completed. This changes from %FALSE to %TRUE after
2319
 * the task’s callback is invoked, and will return %FALSE if called from inside
2320
 * the callback.
2321
 *
2322
 * Returns: %TRUE if the task has completed, %FALSE otherwise.
2323
 *
2324
 * Since: 2.44
2325
 */
2326
gboolean
2327
g_task_get_completed (GTask *task)
2328
0
{
2329
0
  g_return_val_if_fail (G_IS_TASK (task), FALSE);
2330
2331
  /* Convert from a bit field to a boolean. */
2332
0
  return task->completed ? TRUE : FALSE;
2333
0
}
2334
2335
/**
2336
 * g_task_is_valid:
2337
 * @result: (type Gio.AsyncResult): A #GAsyncResult
2338
 * @source_object: (nullable) (type GObject): the source object
2339
 *   expected to be associated with the task
2340
 *
2341
 * Checks that @result is a #GTask, and that @source_object is its
2342
 * source object (or that @source_object is %NULL and @result has no
2343
 * source object). This can be used in g_return_if_fail() checks.
2344
 *
2345
 * Returns: %TRUE if @result and @source_object are valid, %FALSE
2346
 * if not
2347
 *
2348
 * Since: 2.36
2349
 */
2350
gboolean
2351
g_task_is_valid (gpointer result,
2352
                 gpointer source_object)
2353
0
{
2354
0
  if (!G_IS_TASK (result))
2355
0
    return FALSE;
2356
2357
0
  return G_TASK (result)->source_object == source_object;
2358
0
}
2359
2360
static gint
2361
g_task_compare_priority (gconstpointer a,
2362
                         gconstpointer b,
2363
                         gpointer      user_data)
2364
0
{
2365
0
  const GTask *ta = a;
2366
0
  const GTask *tb = b;
2367
0
  gboolean a_cancelled, b_cancelled;
2368
2369
  /* Tasks that are causing other tasks to block have higher
2370
   * priority.
2371
   */
2372
0
  if (ta->blocking_other_task && !tb->blocking_other_task)
2373
0
    return -1;
2374
0
  else if (tb->blocking_other_task && !ta->blocking_other_task)
2375
0
    return 1;
2376
2377
  /* Let already-cancelled tasks finish right away */
2378
0
  a_cancelled = (ta->check_cancellable &&
2379
0
                 g_cancellable_is_cancelled (ta->cancellable));
2380
0
  b_cancelled = (tb->check_cancellable &&
2381
0
                 g_cancellable_is_cancelled (tb->cancellable));
2382
0
  if (a_cancelled && !b_cancelled)
2383
0
    return -1;
2384
0
  else if (b_cancelled && !a_cancelled)
2385
0
    return 1;
2386
2387
  /* Lower priority == run sooner == negative return value */
2388
0
  return ta->priority - tb->priority;
2389
0
}
2390
2391
static gboolean
2392
trivial_source_dispatch (GSource     *source,
2393
                         GSourceFunc  callback,
2394
                         gpointer     user_data)
2395
0
{
2396
0
  return callback (user_data);
2397
0
}
2398
2399
GSourceFuncs trivial_source_funcs = {
2400
  NULL, /* prepare */
2401
  NULL, /* check */
2402
  trivial_source_dispatch,
2403
  NULL, /* finalize */
2404
  NULL, /* closure */
2405
  NULL  /* marshal */
2406
};
2407
2408
static void
2409
g_task_thread_pool_init (void)
2410
0
{
2411
0
  task_pool = g_thread_pool_new (g_task_thread_pool_thread, NULL,
2412
0
                                 G_TASK_POOL_SIZE, FALSE, NULL);
2413
0
  g_assert (task_pool != NULL);
2414
2415
0
  g_thread_pool_set_sort_function (task_pool, g_task_compare_priority, NULL);
2416
2417
0
  task_pool_manager = g_source_new (&trivial_source_funcs, sizeof (GSource));
2418
0
  g_source_set_static_name (task_pool_manager, "GTask thread pool manager");
2419
0
  g_source_set_callback (task_pool_manager, task_pool_manager_timeout, NULL, NULL);
2420
0
  g_source_set_ready_time (task_pool_manager, -1);
2421
0
  g_source_attach (task_pool_manager,
2422
0
                   GLIB_PRIVATE_CALL (g_get_worker_context ()));
2423
0
  g_source_unref (task_pool_manager);
2424
0
}
2425
2426
static void
2427
g_task_get_property (GObject    *object,
2428
                     guint       prop_id,
2429
                     GValue     *value,
2430
                     GParamSpec *pspec)
2431
0
{
2432
0
  GTask *task = G_TASK (object);
2433
2434
0
  switch ((GTaskProperty) prop_id)
2435
0
    {
2436
0
    case PROP_COMPLETED:
2437
0
      g_value_set_boolean (value, g_task_get_completed (task));
2438
0
      break;
2439
0
    }
2440
0
}
2441
2442
static void
2443
g_task_class_init (GTaskClass *klass)
2444
0
{
2445
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2446
2447
0
#ifdef G_ENABLE_DEBUG
2448
0
  gobject_class->constructed = g_task_constructed;
2449
0
#endif
2450
0
  gobject_class->get_property = g_task_get_property;
2451
0
  gobject_class->finalize = g_task_finalize;
2452
2453
  /**
2454
   * GTask:completed:
2455
   *
2456
   * Whether the task has completed, meaning its callback (if set) has been
2457
   * invoked.
2458
   *
2459
   * This can only happen after g_task_return_pointer(),
2460
   * g_task_return_error() or one of the other return functions have been called
2461
   * on the task. However, it is not guaranteed to happen immediately after
2462
   * those functions are called, as the task’s callback may need to be scheduled
2463
   * to run in a different thread.
2464
   *
2465
   * That means it is **not safe** to use this property to track whether a
2466
   * return function has been called on the #GTask. Callers must do that
2467
   * tracking themselves, typically by linking the lifetime of the #GTask to the
2468
   * control flow of their code.
2469
   *
2470
   * This property is guaranteed to change from %FALSE to %TRUE exactly once.
2471
   *
2472
   * The #GObject::notify signal for this change is emitted in the same main
2473
   * context as the task’s callback, immediately after that callback is invoked.
2474
   *
2475
   * Since: 2.44
2476
   */
2477
0
  g_object_class_install_property (gobject_class, PROP_COMPLETED,
2478
0
    g_param_spec_boolean ("completed", NULL, NULL,
2479
0
                          FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2480
2481
0
  if (G_UNLIKELY (task_pool_max_counter == 0))
2482
0
    {
2483
      /* We use two counters to track characteristics of the GTask thread pool.
2484
       * task pool max size - the value of g_thread_pool_set_max_threads()
2485
       * tasks running - the number of running threads
2486
       */
2487
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()");
2488
0
      tasks_running_counter = g_trace_define_int64_counter ("GIO", "tasks running", "Number of currently running tasks in the GTask thread pool");
2489
0
    }
2490
0
}
2491
2492
static gpointer
2493
g_task_get_user_data (GAsyncResult *res)
2494
0
{
2495
0
  return G_TASK (res)->callback_data;
2496
0
}
2497
2498
static gboolean
2499
g_task_is_tagged (GAsyncResult *res,
2500
                  gpointer      source_tag)
2501
0
{
2502
0
  return G_TASK (res)->source_tag == source_tag;
2503
0
}
2504
2505
static void
2506
g_task_async_result_iface_init (GAsyncResultIface *iface)
2507
0
{
2508
0
  iface->get_user_data = g_task_get_user_data;
2509
0
  iface->get_source_object = g_task_ref_source_object;
2510
0
  iface->is_tagged = g_task_is_tagged;
2511
0
}