Coverage Report

Created: 2025-07-23 06:49

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