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