gtask: don't deadlock when tasks block on other tasks
[platform/upstream/glib.git] / gio / tests / task.c
1 /*
2  * Copyright 2012 Red Hat, Inc.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  */
11
12 #include <gio/gio.h>
13
14 static GMainLoop *loop;
15 static GThread *main_thread;
16 static gssize magic;
17
18 /* We need objects for a few tests where we don't care what type
19  * they are, just that they're GObjects.
20  */
21 #define g_dummy_object_new g_socket_client_new
22
23 /* test_basic */
24
25 static void
26 basic_callback (GObject      *object,
27                 GAsyncResult *result,
28                 gpointer      user_data)
29 {
30   gssize *result_out = user_data;
31   GError *error = NULL;
32
33   g_assert (object == NULL);
34   g_assert (g_task_is_valid (result, object));
35   g_assert (g_async_result_get_user_data (result) == user_data);
36   g_assert (!g_task_had_error (G_TASK (result)));
37
38   *result_out = g_task_propagate_int (G_TASK (result), &error);
39   g_assert_no_error (error);
40
41   g_main_loop_quit (loop);
42 }
43
44 static gboolean
45 basic_return (gpointer user_data)
46 {
47   GTask *task = user_data;
48
49   g_task_return_int (task, magic);
50   g_object_unref (task);
51
52   return FALSE;
53 }
54
55 static void
56 basic_destroy_notify (gpointer user_data)
57 {
58   gboolean *destroyed = user_data;
59
60   *destroyed = TRUE;
61 }
62
63 static void
64 test_basic (void)
65 {
66   GTask *task;
67   gssize result;
68   gboolean task_data_destroyed = FALSE;
69
70   task = g_task_new (NULL, NULL, basic_callback, &result);
71   g_task_set_task_data (task, &task_data_destroyed, basic_destroy_notify);
72   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
73
74   g_idle_add (basic_return, task);
75   g_main_loop_run (loop);
76
77   g_assert_cmpint (result, ==, magic);
78   g_assert (task_data_destroyed == TRUE);
79   g_assert (task == NULL);
80 }
81
82 /* test_error */
83
84 static void
85 error_callback (GObject      *object,
86                 GAsyncResult *result,
87                 gpointer      user_data)
88 {
89   gssize *result_out = user_data;
90   GError *error = NULL;
91
92   g_assert (object == NULL);
93   g_assert (g_task_is_valid (result, object));
94   g_assert (g_async_result_get_user_data (result) == user_data);
95   g_assert (g_task_had_error (G_TASK (result)));
96
97   *result_out = g_task_propagate_int (G_TASK (result), &error);
98   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
99   g_error_free (error);
100
101   g_main_loop_quit (loop);
102 }
103
104 static gboolean
105 error_return (gpointer user_data)
106 {
107   GTask *task = user_data;
108
109   g_task_return_new_error (task,
110                            G_IO_ERROR, G_IO_ERROR_FAILED,
111                            "Failed");
112   g_object_unref (task);
113
114   return FALSE;
115 }
116
117 static void
118 error_destroy_notify (gpointer user_data)
119 {
120   gboolean *destroyed = user_data;
121
122   *destroyed = TRUE;
123 }
124
125 static void
126 test_error (void)
127 {
128   GTask *task;
129   gssize result;
130   gboolean first_task_data_destroyed = FALSE;
131   gboolean second_task_data_destroyed = FALSE;
132
133   task = g_task_new (NULL, NULL, error_callback, &result);
134   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
135
136   g_assert (first_task_data_destroyed == FALSE);
137   g_task_set_task_data (task, &first_task_data_destroyed, error_destroy_notify);
138   g_assert (first_task_data_destroyed == FALSE);
139
140   /* Calling g_task_set_task_data() again will destroy the first data */
141   g_task_set_task_data (task, &second_task_data_destroyed, error_destroy_notify);
142   g_assert (first_task_data_destroyed == TRUE);
143   g_assert (second_task_data_destroyed == FALSE);
144
145   g_idle_add (error_return, task);
146   g_main_loop_run (loop);
147
148   g_assert_cmpint (result, ==, -1);
149   g_assert (second_task_data_destroyed == TRUE);
150   g_assert (task == NULL);
151 }
152
153 /* test_return_from_same_iteration: calling g_task_return_* from the
154  * loop iteration the task was created in defers completion until the
155  * next iteration.
156  */
157 gboolean same_result = FALSE;
158
159 static void
160 same_callback (GObject      *object,
161                GAsyncResult *result,
162                gpointer      user_data)
163 {
164   gboolean *result_out = user_data;
165   GError *error = NULL;
166
167   g_assert (object == NULL);
168   g_assert (g_task_is_valid (result, object));
169   g_assert (g_async_result_get_user_data (result) == user_data);
170   g_assert (!g_task_had_error (G_TASK (result)));
171
172   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
173   g_assert_no_error (error);
174
175   g_main_loop_quit (loop);
176 }
177
178 static gboolean
179 same_start (gpointer user_data)
180 {
181   gpointer *weak_pointer = user_data;
182   GTask *task;
183
184   task = g_task_new (NULL, NULL, same_callback, &same_result);
185   *weak_pointer = task;
186   g_object_add_weak_pointer (G_OBJECT (task), weak_pointer);
187
188   g_task_return_boolean (task, TRUE);
189   g_object_unref (task);
190
191   /* same_callback should not have been invoked yet */
192   g_assert (same_result == FALSE);
193   g_assert (*weak_pointer == task);
194
195   return FALSE;
196 }
197
198 static void
199 test_return_from_same_iteration (void)
200 {
201   gpointer weak_pointer;
202
203   g_idle_add (same_start, &weak_pointer);
204   g_main_loop_run (loop);
205
206   g_assert (same_result == TRUE);
207   g_assert (weak_pointer == NULL);
208 }
209
210 /* test_return_from_toplevel: calling g_task_return_* from outside any
211  * main loop completes the task inside the main loop.
212  */
213
214 static void
215 toplevel_callback (GObject      *object,
216               GAsyncResult *result,
217               gpointer      user_data)
218 {
219   gboolean *result_out = user_data;
220   GError *error = NULL;
221
222   g_assert (object == NULL);
223   g_assert (g_task_is_valid (result, object));
224   g_assert (g_async_result_get_user_data (result) == user_data);
225   g_assert (!g_task_had_error (G_TASK (result)));
226
227   *result_out = g_task_propagate_boolean (G_TASK (result), &error);
228   g_assert_no_error (error);
229
230   g_main_loop_quit (loop);
231 }
232
233 static void
234 test_return_from_toplevel (void)
235 {
236   GTask *task;
237   gboolean result = FALSE;
238
239   task = g_task_new (NULL, NULL, toplevel_callback, &result);
240   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
241
242   g_task_return_boolean (task, TRUE);
243   g_object_unref (task);
244
245   /* toplevel_callback should not have been invoked yet */
246   g_assert (result == FALSE);
247   g_assert (task != NULL);
248
249   g_main_loop_run (loop);
250
251   g_assert (result == TRUE);
252   g_assert (task == NULL);
253 }
254
255 /* test_return_from_anon_thread: calling g_task_return_* from a
256  * thread with no thread-default main context will complete the
257  * task in the task's context/thread.
258  */
259
260 GThread *anon_thread;
261
262 static void
263 anon_callback (GObject      *object,
264                GAsyncResult *result,
265                gpointer      user_data)
266 {
267   gssize *result_out = user_data;
268   GError *error = NULL;
269
270   g_assert (object == NULL);
271   g_assert (g_task_is_valid (result, object));
272   g_assert (g_async_result_get_user_data (result) == user_data);
273   g_assert (!g_task_had_error (G_TASK (result)));
274
275   g_assert (g_thread_self () == main_thread);
276
277   *result_out = g_task_propagate_int (G_TASK (result), &error);
278   g_assert_no_error (error);
279
280   g_main_loop_quit (loop);
281 }
282
283 static gpointer
284 anon_thread_func (gpointer user_data)
285 {
286   GTask *task = user_data;
287
288   g_task_return_int (task, magic);
289   g_object_unref (task);
290
291   return NULL;
292 }
293
294 static gboolean
295 anon_start (gpointer user_data)
296 {
297   GTask *task = user_data;
298
299   anon_thread = g_thread_new ("test_return_from_anon_thread",
300                               anon_thread_func, task);
301   return FALSE;
302 }
303
304 static void
305 test_return_from_anon_thread (void)
306 {
307   GTask *task;
308   gssize result = 0;
309
310   task = g_task_new (NULL, NULL, anon_callback, &result);
311   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
312
313   g_idle_add (anon_start, task);
314   g_main_loop_run (loop);
315
316   g_thread_join (anon_thread);
317
318   g_assert_cmpint (result, ==, magic);
319   g_assert (task == NULL);
320 }
321
322 /* test_return_from_wrong_thread: calling g_task_return_* from a
323  * thread with its own thread-default main context will complete the
324  * task in the task's context/thread.
325  */
326
327 GThread *wrong_thread;
328
329 static void
330 wrong_callback (GObject      *object,
331                GAsyncResult *result,
332                gpointer      user_data)
333 {
334   gssize *result_out = user_data;
335   GError *error = NULL;
336
337   g_assert (object == NULL);
338   g_assert (g_task_is_valid (result, object));
339   g_assert (g_async_result_get_user_data (result) == user_data);
340   g_assert (!g_task_had_error (G_TASK (result)));
341
342   g_assert (g_thread_self () == main_thread);
343
344   *result_out = g_task_propagate_int (G_TASK (result), &error);
345   g_assert_no_error (error);
346
347   g_main_loop_quit (loop);
348 }
349
350 static gpointer
351 wrong_thread_func (gpointer user_data)
352 {
353   GTask *task = user_data;
354   GMainContext *context;
355
356   context = g_main_context_new ();
357   g_main_context_push_thread_default (context);
358
359   g_assert (g_task_get_context (task) != context);
360
361   g_task_return_int (task, magic);
362   g_object_unref (task);
363
364   g_main_context_pop_thread_default (context);
365   g_main_context_unref (context);
366
367   return NULL;
368 }
369
370 static gboolean
371 wrong_start (gpointer user_data)
372 {
373   GTask *task = user_data;
374
375   wrong_thread = g_thread_new ("test_return_from_anon_thread",
376                                wrong_thread_func, task);
377   return FALSE;
378 }
379
380 static void
381 test_return_from_wrong_thread (void)
382 {
383   GTask *task;
384   gssize result = 0;
385
386   task = g_task_new (NULL, NULL, wrong_callback, &result);
387   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
388
389   g_idle_add (wrong_start, task);
390   g_main_loop_run (loop);
391
392   g_thread_join (wrong_thread);
393
394   g_assert_cmpint (result, ==, magic);
395   g_assert (task == NULL);
396 }
397
398 /* test_no_callback */
399
400 static void
401 test_no_callback (void)
402 {
403   GTask *task;
404
405   task = g_task_new (NULL, NULL, NULL, NULL);
406   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
407
408   g_task_return_boolean (task, TRUE);
409   g_object_unref (task);
410
411   /* Since there's no callback, g_task_return_boolean() will
412    * not have queued an idle source and taken a ref on task,
413    * so we just dropped the last ref.
414    */
415   g_assert (task == NULL);
416 }
417
418 /* test_report_error */
419
420 static void test_report_error (void);
421
422 static void
423 report_callback (GObject      *object,
424                  GAsyncResult *result,
425                  gpointer      user_data)
426 {
427   gpointer *weak_pointer = user_data;
428   GError *error = NULL;
429   gssize ret;
430
431   g_assert (object == NULL);
432   g_assert (g_task_is_valid (result, object));
433   g_assert (g_async_result_get_user_data (result) == user_data);
434   g_assert (g_async_result_is_tagged (result, test_report_error));
435   g_assert (g_task_get_source_tag (G_TASK (result)) == test_report_error);
436   g_assert (g_task_had_error (G_TASK (result)));
437
438   ret = g_task_propagate_int (G_TASK (result), &error);
439   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
440   g_assert_cmpint (ret, ==, -1);
441   g_error_free (error);
442
443   *weak_pointer = result;
444   g_object_add_weak_pointer (G_OBJECT (result), weak_pointer);
445
446   g_main_loop_quit (loop);
447 }
448
449 static void
450 test_report_error (void)
451 {
452   gpointer weak_pointer = (gpointer)-1;
453
454   g_task_report_new_error (NULL, report_callback, &weak_pointer,
455                            test_report_error,
456                            G_IO_ERROR, G_IO_ERROR_FAILED,
457                            "Failed");
458   g_main_loop_run (loop);
459
460   g_assert (weak_pointer == NULL);
461 }
462
463 /* test_priority: tasks complete in priority order */
464
465 static int counter = 0;
466
467 static void
468 priority_callback (GObject      *object,
469                    GAsyncResult *result,
470                    gpointer      user_data)
471 {
472   gssize *ret_out = user_data;
473   GError *error = NULL;
474
475   g_assert (object == NULL);
476   g_assert (g_task_is_valid (result, object));
477   g_assert (g_async_result_get_user_data (result) == user_data);
478   g_assert (!g_task_had_error (G_TASK (result)));
479
480   g_task_propagate_boolean (G_TASK (result), &error);
481   g_assert_no_error (error);
482
483   *ret_out = ++counter;
484
485   if (counter == 3)
486     g_main_loop_quit (loop);
487 }
488
489 static void
490 test_priority (void)
491 {
492   GTask *t1, *t2, *t3;
493   gssize ret1, ret2, ret3;
494
495   /* t2 has higher priority than either t1 or t3, so we can't
496    * accidentally pass the test just by completing the tasks in the
497    * order they were created (or in reverse order).
498    */
499
500   t1 = g_task_new (NULL, NULL, priority_callback, &ret1);
501   g_task_set_priority (t1, G_PRIORITY_DEFAULT);
502   g_task_return_boolean (t1, TRUE);
503   g_object_unref (t1);
504
505   t2 = g_task_new (NULL, NULL, priority_callback, &ret2);
506   g_task_set_priority (t2, G_PRIORITY_HIGH);
507   g_task_return_boolean (t2, TRUE);
508   g_object_unref (t2);
509
510   t3 = g_task_new (NULL, NULL, priority_callback, &ret3);
511   g_task_set_priority (t3, G_PRIORITY_LOW);
512   g_task_return_boolean (t3, TRUE);
513   g_object_unref (t3);
514
515   g_main_loop_run (loop);
516
517   g_assert_cmpint (ret2, ==, 1);
518   g_assert_cmpint (ret1, ==, 2);
519   g_assert_cmpint (ret3, ==, 3);
520 }
521
522 /* test_check_cancellable: cancellation overrides return value */
523
524 enum {
525   CANCEL_BEFORE     = (1 << 1),
526   CANCEL_AFTER      = (1 << 2),
527   CHECK_CANCELLABLE = (1 << 3)
528 };
529 #define NUM_CANCEL_TESTS (CANCEL_BEFORE | CANCEL_AFTER | CHECK_CANCELLABLE)
530
531 static void
532 cancel_callback (GObject      *object,
533                  GAsyncResult *result,
534                  gpointer      user_data)
535 {
536   int state = GPOINTER_TO_INT (user_data);
537   GTask *task;
538   GCancellable *cancellable;
539   GError *error = NULL;
540
541   g_assert (object == NULL);
542   g_assert (g_task_is_valid (result, object));
543   g_assert (g_async_result_get_user_data (result) == user_data);
544
545   task = G_TASK (result);
546   cancellable = g_task_get_cancellable (task);
547   g_assert (G_IS_CANCELLABLE (cancellable));
548
549   if (state & (CANCEL_BEFORE | CANCEL_AFTER))
550     g_assert (g_cancellable_is_cancelled (cancellable));
551   else
552     g_assert (!g_cancellable_is_cancelled (cancellable));
553
554   if (state & CHECK_CANCELLABLE)
555     g_assert (g_task_get_check_cancellable (task));
556   else
557     g_assert (!g_task_get_check_cancellable (task));
558
559   if (g_task_propagate_boolean (task, &error))
560     {
561       g_assert (!g_cancellable_is_cancelled (cancellable) ||
562                 !g_task_get_check_cancellable (task));
563     }
564   else
565     {
566       g_assert (g_cancellable_is_cancelled (cancellable) &&
567                 g_task_get_check_cancellable (task));
568       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
569       g_error_free (error);
570     }
571
572   g_main_loop_quit (loop);
573 }
574
575 static void
576 test_check_cancellable (void)
577 {
578   GTask *task;
579   GCancellable *cancellable;
580   int state;
581
582   cancellable = g_cancellable_new ();
583
584   for (state = 0; state <= NUM_CANCEL_TESTS; state++)
585     {
586       task = g_task_new (NULL, cancellable, cancel_callback,
587                          GINT_TO_POINTER (state));
588       g_task_set_check_cancellable (task, (state & CHECK_CANCELLABLE) != 0);
589
590       if (state & CANCEL_BEFORE)
591         g_cancellable_cancel (cancellable);
592       g_task_return_boolean (task, TRUE);
593       if (state & CANCEL_AFTER)
594         g_cancellable_cancel (cancellable);
595
596       g_main_loop_run (loop);
597       g_object_unref (task);
598       g_cancellable_reset (cancellable);
599     }
600
601   g_object_unref (cancellable);
602 }
603
604 /* test_return_if_cancelled */
605
606 static void
607 return_if_cancelled_callback (GObject      *object,
608                               GAsyncResult *result,
609                               gpointer      user_data)
610 {
611   GError *error = NULL;
612
613   g_assert (object == NULL);
614   g_assert (g_task_is_valid (result, object));
615   g_assert (g_async_result_get_user_data (result) == user_data);
616   g_assert (g_task_had_error (G_TASK (result)));
617
618   g_task_propagate_boolean (G_TASK (result), &error);
619   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
620   g_clear_error (&error);
621
622   g_main_loop_quit (loop);
623 }
624
625 static void
626 test_return_if_cancelled (void)
627 {
628   GTask *task;
629   GCancellable *cancellable;
630   gboolean cancelled;
631
632   cancellable = g_cancellable_new ();
633
634   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
635   g_cancellable_cancel (cancellable);
636   cancelled = g_task_return_error_if_cancelled (task);
637   g_assert (cancelled);
638   g_main_loop_run (loop);
639   g_object_unref (task);
640   g_cancellable_reset (cancellable);
641
642   task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
643   g_task_set_check_cancellable (task, FALSE);
644   g_cancellable_cancel (cancellable);
645   cancelled = g_task_return_error_if_cancelled (task);
646   g_assert (cancelled);
647   g_main_loop_run (loop);
648   g_object_unref (task);
649   g_object_unref (cancellable);
650 }
651
652 /* test_run_in_thread */
653
654 static void
655 run_in_thread_callback (GObject      *object,
656                         GAsyncResult *result,
657                         gpointer      user_data)
658 {
659   gboolean *done = user_data;
660   GError *error = NULL;
661   gssize ret;
662
663   g_assert (g_thread_self () == main_thread);
664
665   g_assert (object == NULL);
666   g_assert (g_task_is_valid (result, object));
667   g_assert (g_async_result_get_user_data (result) == user_data);
668   g_assert (!g_task_had_error (G_TASK (result)));
669
670   ret = g_task_propagate_int (G_TASK (result), &error);
671   g_assert_no_error (error);
672   g_assert_cmpint (ret, ==, magic);
673
674   *done = TRUE;
675   g_main_loop_quit (loop);
676 }
677
678 static void
679 run_in_thread_thread (GTask        *task,
680                       gpointer      source_object,
681                       gpointer      task_data,
682                       GCancellable *cancellable)
683 {
684   gboolean *thread_ran = task_data;
685
686   g_assert (source_object == g_task_get_source_object (task));
687   g_assert (task_data == g_task_get_task_data (task));
688   g_assert (cancellable == g_task_get_cancellable (task));
689
690   g_assert (g_thread_self () != main_thread);
691
692   *thread_ran = TRUE;
693   g_task_return_int (task, magic);
694 }
695
696 static void
697 test_run_in_thread (void)
698 {
699   GTask *task;
700   volatile gboolean thread_ran = FALSE;
701   gboolean done = FALSE;
702
703   task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
704   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
705
706   g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
707   g_task_run_in_thread (task, run_in_thread_thread);
708   g_object_unref (task);
709
710   while (!thread_ran)
711     g_usleep (100);
712
713   g_assert (done == FALSE);
714   g_assert (task != NULL);
715
716   g_main_loop_run (loop);
717
718   g_assert (done == TRUE);
719   g_assert (task == NULL);
720 }
721
722 /* test_run_in_thread_sync */
723
724 static void
725 run_in_thread_sync_callback (GObject      *object,
726                              GAsyncResult *result,
727                              gpointer      user_data)
728 {
729   /* g_task_run_in_thread_sync() does not invoke the task's callback */
730   g_assert_not_reached ();
731 }
732
733 static void
734 run_in_thread_sync_thread (GTask        *task,
735                            gpointer      source_object,
736                            gpointer      task_data,
737                            GCancellable *cancellable)
738 {
739   gboolean *thread_ran = task_data;
740
741   g_assert (source_object == g_task_get_source_object (task));
742   g_assert (task_data == g_task_get_task_data (task));
743   g_assert (cancellable == g_task_get_cancellable (task));
744
745   g_assert (g_thread_self () != main_thread);
746
747   *thread_ran = TRUE;
748   g_task_return_int (task, magic);
749 }
750
751 static void
752 test_run_in_thread_sync (void)
753 {
754   GTask *task;
755   gboolean thread_ran = FALSE;
756   gssize ret;
757   GError *error = NULL;
758
759   task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
760
761   g_task_set_task_data (task, &thread_ran, NULL);
762   g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
763
764   g_assert (thread_ran == TRUE);
765   g_assert (task != NULL);
766   g_assert (!g_task_had_error (task));
767
768   ret = g_task_propagate_int (task, &error);
769   g_assert_no_error (error);
770   g_assert_cmpint (ret, ==, magic);
771
772   g_object_unref (task);
773 }
774
775 /* test_run_in_thread_priority */
776
777 static GMutex fake_task_mutex, last_fake_task_mutex;
778 static gint sequence_number = 0;
779
780 static void
781 quit_main_loop_callback (GObject      *object,
782                          GAsyncResult *result,
783                          gpointer      user_data)
784 {
785   GError *error = NULL;
786   gboolean ret;
787
788   g_assert (g_thread_self () == main_thread);
789
790   g_assert (object == NULL);
791   g_assert (g_task_is_valid (result, object));
792   g_assert (g_async_result_get_user_data (result) == user_data);
793   g_assert (!g_task_had_error (G_TASK (result)));
794
795   ret = g_task_propagate_boolean (G_TASK (result), &error);
796   g_assert_no_error (error);
797   g_assert_cmpint (ret, ==, TRUE);
798
799   g_main_loop_quit (loop);
800 }
801
802 static void
803 set_sequence_number_thread (GTask        *task,
804                             gpointer      source_object,
805                             gpointer      task_data,
806                             GCancellable *cancellable)
807 {
808   gint *seq_no_p = task_data;
809
810   *seq_no_p = ++sequence_number;
811   g_task_return_boolean (task, TRUE);
812 }
813
814 static void
815 fake_task_thread (GTask        *task,
816                   gpointer      source_object,
817                   gpointer      task_data,
818                   GCancellable *cancellable)
819 {
820   GMutex *mutex = task_data;
821
822   g_mutex_lock (mutex);
823   g_mutex_unlock (mutex);
824   g_task_return_boolean (task, TRUE);
825 }
826
827 #define G_TASK_THREAD_POOL_SIZE 10
828 static int fake_tasks_running;
829
830 static void
831 fake_task_callback (GObject      *source,
832                     GAsyncResult *result,
833                     gpointer      user_data)
834 {
835   if (--fake_tasks_running == 0)
836     g_main_loop_quit (loop);
837 }
838
839 static void
840 clog_up_thread_pool (void)
841 {
842   GTask *task;
843   int i;
844
845   g_thread_pool_stop_unused_threads ();
846
847   g_mutex_lock (&fake_task_mutex);
848   for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
849     {
850       task = g_task_new (NULL, NULL, fake_task_callback, NULL);
851       g_task_set_task_data (task, &fake_task_mutex, NULL);
852       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
853       g_task_set_priority (task, G_PRIORITY_HIGH * 2);
854       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
855       g_task_run_in_thread (task, fake_task_thread);
856       g_object_unref (task);
857       fake_tasks_running++;
858     }
859
860   g_mutex_lock (&last_fake_task_mutex);
861   task = g_task_new (NULL, NULL, NULL, NULL);
862   g_task_set_task_data (task, &last_fake_task_mutex, NULL);
863   g_task_set_priority (task, G_PRIORITY_HIGH * 2);
864   g_task_run_in_thread (task, fake_task_thread);
865   g_object_unref (task);
866 }
867
868 static void
869 unclog_thread_pool (void)
870 {
871   g_mutex_unlock (&fake_task_mutex);
872   g_main_loop_run (loop);
873 }
874
875 static void
876 test_run_in_thread_priority (void)
877 {
878   GTask *task;
879   GCancellable *cancellable;
880   int seq_a, seq_b, seq_c, seq_d;
881
882   clog_up_thread_pool ();
883
884   /* Queue three more tasks that we'll arrange to have run serially */
885   task = g_task_new (NULL, NULL, NULL, NULL);
886   g_task_set_task_data (task, &seq_a, NULL);
887   g_task_run_in_thread (task, set_sequence_number_thread);
888   g_object_unref (task);
889   
890   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
891   g_task_set_task_data (task, &seq_b, NULL);
892   g_task_set_priority (task, G_PRIORITY_LOW);
893   g_task_run_in_thread (task, set_sequence_number_thread);
894   g_object_unref (task);
895   
896   task = g_task_new (NULL, NULL, NULL, NULL);
897   g_task_set_task_data (task, &seq_c, NULL);
898   g_task_set_priority (task, G_PRIORITY_HIGH);
899   g_task_run_in_thread (task, set_sequence_number_thread);
900   g_object_unref (task);
901   
902   cancellable = g_cancellable_new ();
903   task = g_task_new (NULL, cancellable, NULL, NULL);
904   g_task_set_task_data (task, &seq_d, NULL);
905   g_task_run_in_thread (task, set_sequence_number_thread);
906   g_cancellable_cancel (cancellable);
907   g_object_unref (cancellable);
908   g_object_unref (task);
909
910   /* Let the last fake task complete; the four other tasks will then
911    * complete serially, in the order D, C, A, B, and B will quit the
912    * main loop.
913    */
914   g_mutex_unlock (&last_fake_task_mutex);
915   g_main_loop_run (loop);
916
917   g_assert_cmpint (seq_d, ==, 1);
918   g_assert_cmpint (seq_c, ==, 2);
919   g_assert_cmpint (seq_a, ==, 3);
920   g_assert_cmpint (seq_b, ==, 4);
921
922   unclog_thread_pool ();
923 }
924
925 /* test_run_in_thread_nested: task threads that block waiting on
926  * other task threads will not cause the thread pool to starve.
927  */
928
929 static void
930 run_nested_task_thread (GTask        *task,
931                         gpointer      source_object,
932                         gpointer      task_data,
933                         GCancellable *cancellable)
934 {
935   GTask *nested;
936   int *nested_tasks_left = task_data;
937
938   if ((*nested_tasks_left)--)
939     {
940       nested = g_task_new (NULL, NULL, NULL, NULL);
941       g_task_set_task_data (nested, nested_tasks_left, NULL);
942       g_task_run_in_thread_sync (nested, run_nested_task_thread);
943       g_object_unref (nested);
944     }
945
946   g_task_return_boolean (task, TRUE);
947 }
948
949 static void
950 test_run_in_thread_nested (void)
951 {
952   GTask *task;
953   int nested_tasks_left = 2;
954
955   clog_up_thread_pool ();
956
957   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
958   g_task_set_task_data (task, &nested_tasks_left, NULL);
959   g_task_run_in_thread (task, run_nested_task_thread);
960   g_object_unref (task);
961
962   g_mutex_unlock (&last_fake_task_mutex);
963   g_main_loop_run (loop);
964
965   unclog_thread_pool ();
966 }
967
968 /* test_return_on_cancel */
969
970 GMutex roc_init_mutex, roc_finish_mutex;
971 GCond roc_init_cond, roc_finish_cond;
972
973 typedef enum {
974   THREAD_STARTING,
975   THREAD_RUNNING,
976   THREAD_CANCELLED,
977   THREAD_COMPLETED
978 } ThreadState;
979
980 static void
981 return_on_cancel_callback (GObject      *object,
982                            GAsyncResult *result,
983                            gpointer      user_data)
984 {
985   gboolean *callback_ran = user_data;
986   GError *error = NULL;
987   gssize ret;
988
989   g_assert (g_thread_self () == main_thread);
990
991   g_assert (object == NULL);
992   g_assert (g_task_is_valid (result, object));
993   g_assert (g_async_result_get_user_data (result) == user_data);
994   g_assert (g_task_had_error (G_TASK (result)));
995
996   ret = g_task_propagate_int (G_TASK (result), &error);
997   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
998   g_clear_error (&error);
999   g_assert_cmpint (ret, ==, -1);
1000
1001   *callback_ran = TRUE;
1002   g_main_loop_quit (loop);
1003 }
1004
1005 static void
1006 return_on_cancel_thread (GTask        *task,
1007                          gpointer      source_object,
1008                          gpointer      task_data,
1009                          GCancellable *cancellable)
1010 {
1011   ThreadState *state = task_data;
1012
1013   g_assert (source_object == g_task_get_source_object (task));
1014   g_assert (task_data == g_task_get_task_data (task));
1015   g_assert (cancellable == g_task_get_cancellable (task));
1016
1017   g_assert (g_thread_self () != main_thread);
1018
1019   g_mutex_lock (&roc_init_mutex);
1020   *state = THREAD_RUNNING;
1021   g_cond_signal (&roc_init_cond);
1022   g_mutex_unlock (&roc_init_mutex);
1023
1024   g_mutex_lock (&roc_finish_mutex);
1025
1026   if (!g_task_get_return_on_cancel (task) ||
1027       g_task_set_return_on_cancel (task, FALSE))
1028     {
1029       *state = THREAD_COMPLETED;
1030       g_task_return_int (task, magic);
1031     }
1032   else
1033     *state = THREAD_CANCELLED;
1034
1035   g_cond_signal (&roc_finish_cond);
1036   g_mutex_unlock (&roc_finish_mutex);
1037 }
1038
1039 static void
1040 test_return_on_cancel (void)
1041 {
1042   GTask *task;
1043   GCancellable *cancellable;
1044   volatile ThreadState thread_state;
1045   gboolean callback_ran;
1046
1047   cancellable = g_cancellable_new ();
1048
1049   /* If return-on-cancel is FALSE (default), the task does not return
1050    * early.
1051    */
1052   callback_ran = FALSE;
1053   thread_state = THREAD_STARTING;
1054   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1055
1056   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1057   g_mutex_lock (&roc_init_mutex);
1058   g_mutex_lock (&roc_finish_mutex);
1059   g_task_run_in_thread (task, return_on_cancel_thread);
1060   g_object_unref (task);
1061
1062   while (thread_state == THREAD_STARTING)
1063     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1064   g_mutex_unlock (&roc_init_mutex);
1065
1066   g_assert (thread_state == THREAD_RUNNING);
1067   g_assert (callback_ran == FALSE);
1068
1069   g_cancellable_cancel (cancellable);
1070   g_mutex_unlock (&roc_finish_mutex);
1071   g_main_loop_run (loop);
1072
1073   g_assert (thread_state == THREAD_COMPLETED);
1074   g_assert (callback_ran == TRUE);
1075
1076   g_cancellable_reset (cancellable);
1077
1078   /* If return-on-cancel is TRUE, it does return early */
1079   callback_ran = FALSE;
1080   thread_state = THREAD_STARTING;
1081   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1082   g_task_set_return_on_cancel (task, TRUE);
1083
1084   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1085   g_mutex_lock (&roc_init_mutex);
1086   g_mutex_lock (&roc_finish_mutex);
1087   g_task_run_in_thread (task, return_on_cancel_thread);
1088   g_object_unref (task);
1089
1090   while (thread_state == THREAD_STARTING)
1091     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1092   g_mutex_unlock (&roc_init_mutex);
1093
1094   g_assert (thread_state == THREAD_RUNNING);
1095   g_assert (callback_ran == FALSE);
1096
1097   g_cancellable_cancel (cancellable);
1098   g_main_loop_run (loop);
1099   g_assert (thread_state == THREAD_RUNNING);
1100   g_assert (callback_ran == TRUE);
1101
1102   while (thread_state == THREAD_RUNNING)
1103     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1104   g_mutex_unlock (&roc_finish_mutex);
1105
1106   g_assert (thread_state == THREAD_CANCELLED);
1107   /* We can't g_assert (task == NULL) here because it won't become NULL
1108    * until a little bit after roc_finish_cond is signaled.
1109    */
1110
1111   g_cancellable_reset (cancellable);
1112
1113   /* If the task is already cancelled before it starts, it returns
1114    * immediately, but the thread func still runs.
1115    */
1116   callback_ran = FALSE;
1117   thread_state = THREAD_STARTING;
1118   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1119   g_task_set_return_on_cancel (task, TRUE);
1120
1121   g_cancellable_cancel (cancellable);
1122
1123   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1124   g_mutex_lock (&roc_init_mutex);
1125   g_mutex_lock (&roc_finish_mutex);
1126   g_task_run_in_thread (task, return_on_cancel_thread);
1127   g_object_unref (task);
1128
1129   g_main_loop_run (loop);
1130   g_assert (callback_ran == TRUE);
1131
1132   while (thread_state == THREAD_STARTING)
1133     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1134   g_mutex_unlock (&roc_init_mutex);
1135
1136   g_assert (thread_state == THREAD_RUNNING);
1137
1138   while (thread_state == THREAD_RUNNING)
1139     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1140   g_mutex_unlock (&roc_finish_mutex);
1141
1142   g_assert (thread_state == THREAD_CANCELLED);
1143
1144   g_object_unref (cancellable);
1145 }
1146
1147 /* test_return_on_cancel_sync */
1148
1149 static gpointer
1150 cancel_sync_runner_thread (gpointer task)
1151 {
1152   g_task_run_in_thread_sync (task, return_on_cancel_thread);
1153   return NULL;
1154 }
1155
1156 static void
1157 test_return_on_cancel_sync (void)
1158 {
1159   GTask *task;
1160   GCancellable *cancellable;
1161   volatile ThreadState thread_state;
1162   GThread *runner_thread;
1163   gssize ret;
1164   GError *error = NULL;
1165
1166   cancellable = g_cancellable_new ();
1167
1168   /* If return-on-cancel is FALSE, the task does not return early.
1169    */
1170   thread_state = THREAD_STARTING;
1171   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1172
1173   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1174   g_mutex_lock (&roc_init_mutex);
1175   g_mutex_lock (&roc_finish_mutex);
1176   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1177                                 cancel_sync_runner_thread, task);
1178
1179   while (thread_state == THREAD_STARTING)
1180     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1181   g_mutex_unlock (&roc_init_mutex);
1182
1183   g_assert (thread_state == THREAD_RUNNING);
1184
1185   g_cancellable_cancel (cancellable);
1186   g_mutex_unlock (&roc_finish_mutex);
1187   g_thread_join (runner_thread);
1188   g_assert (thread_state == THREAD_COMPLETED);
1189
1190   ret = g_task_propagate_int (task, &error);
1191   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1192   g_clear_error (&error);
1193   g_assert_cmpint (ret, ==, -1);
1194
1195   g_object_unref (task);
1196
1197   g_cancellable_reset (cancellable);
1198
1199   /* If return-on-cancel is TRUE, it does return early */
1200   thread_state = THREAD_STARTING;
1201   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1202   g_task_set_return_on_cancel (task, TRUE);
1203
1204   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1205   g_mutex_lock (&roc_init_mutex);
1206   g_mutex_lock (&roc_finish_mutex);
1207   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1208                                 cancel_sync_runner_thread, task);
1209
1210   while (thread_state == THREAD_STARTING)
1211     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1212   g_mutex_unlock (&roc_init_mutex);
1213
1214   g_assert (thread_state == THREAD_RUNNING);
1215
1216   g_cancellable_cancel (cancellable);
1217   g_thread_join (runner_thread);
1218   g_assert (thread_state == THREAD_RUNNING);
1219
1220   ret = g_task_propagate_int (task, &error);
1221   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1222   g_clear_error (&error);
1223   g_assert_cmpint (ret, ==, -1);
1224
1225   g_object_unref (task);
1226
1227   while (thread_state == THREAD_RUNNING)
1228     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1229   g_mutex_unlock (&roc_finish_mutex);
1230
1231   g_assert (thread_state == THREAD_CANCELLED);
1232
1233   g_cancellable_reset (cancellable);
1234
1235   /* If the task is already cancelled before it starts, it returns
1236    * immediately, but the thread func still runs.
1237    */
1238   thread_state = THREAD_STARTING;
1239   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1240   g_task_set_return_on_cancel (task, TRUE);
1241
1242   g_cancellable_cancel (cancellable);
1243
1244   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1245   g_mutex_lock (&roc_init_mutex);
1246   g_mutex_lock (&roc_finish_mutex);
1247   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1248                                 cancel_sync_runner_thread, task);
1249
1250   g_thread_join (runner_thread);
1251   g_assert (thread_state == THREAD_STARTING);
1252
1253   ret = g_task_propagate_int (task, &error);
1254   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1255   g_clear_error (&error);
1256   g_assert_cmpint (ret, ==, -1);
1257
1258   g_object_unref (task);
1259
1260   while (thread_state == THREAD_STARTING)
1261     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1262   g_mutex_unlock (&roc_init_mutex);
1263
1264   g_assert (thread_state == THREAD_RUNNING);
1265
1266   while (thread_state == THREAD_RUNNING)
1267     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1268   g_mutex_unlock (&roc_finish_mutex);
1269
1270   g_assert (thread_state == THREAD_CANCELLED);
1271
1272   g_object_unref (cancellable);
1273 }
1274
1275 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1276  * non-racy
1277  */
1278
1279 GMutex roca_mutex_1, roca_mutex_2;
1280 GCond roca_cond_1, roca_cond_2;
1281
1282 static void
1283 return_on_cancel_atomic_callback (GObject      *object,
1284                                   GAsyncResult *result,
1285                                   gpointer      user_data)
1286 {
1287   gboolean *callback_ran = user_data;
1288   GError *error = NULL;
1289   gssize ret;
1290
1291   g_assert (g_thread_self () == main_thread);
1292
1293   g_assert (object == NULL);
1294   g_assert (g_task_is_valid (result, object));
1295   g_assert (g_async_result_get_user_data (result) == user_data);
1296   g_assert (g_task_had_error (G_TASK (result)));
1297
1298   ret = g_task_propagate_int (G_TASK (result), &error);
1299   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1300   g_clear_error (&error);
1301   g_assert_cmpint (ret, ==, -1);
1302
1303   *callback_ran = TRUE;
1304   g_main_loop_quit (loop);
1305 }
1306
1307 static gboolean
1308 idle_quit_loop (gpointer user_data)
1309 {
1310   g_main_loop_quit (loop);
1311   return FALSE;
1312 }
1313
1314 static void
1315 return_on_cancel_atomic_thread (GTask        *task,
1316                                 gpointer      source_object,
1317                                 gpointer      task_data,
1318                                 GCancellable *cancellable)
1319 {
1320   gint *state = task_data;
1321
1322   g_assert (source_object == g_task_get_source_object (task));
1323   g_assert (task_data == g_task_get_task_data (task));
1324   g_assert (cancellable == g_task_get_cancellable (task));
1325
1326   g_assert (g_thread_self () != main_thread);
1327   g_assert_cmpint (*state, ==, 0);
1328
1329   g_mutex_lock (&roca_mutex_1);
1330   *state = 1;
1331   g_cond_signal (&roca_cond_1);
1332   g_mutex_unlock (&roca_mutex_1);
1333
1334   g_mutex_lock (&roca_mutex_2);
1335   if (g_task_set_return_on_cancel (task, FALSE))
1336     *state = 2;
1337   else
1338     *state = 3;
1339   g_cond_signal (&roca_cond_2);
1340   g_mutex_unlock (&roca_mutex_2);
1341
1342   g_mutex_lock (&roca_mutex_1);
1343   if (g_task_set_return_on_cancel (task, TRUE))
1344     *state = 4;
1345   else
1346     *state = 5;
1347   g_cond_signal (&roca_cond_1);
1348   g_mutex_unlock (&roca_mutex_1);
1349
1350   g_mutex_lock (&roca_mutex_2);
1351   if (g_task_set_return_on_cancel (task, TRUE))
1352     *state = 6;
1353   else
1354     *state = 7;
1355   g_cond_signal (&roca_cond_2);
1356   g_mutex_unlock (&roca_mutex_2);
1357
1358   g_task_return_int (task, magic);
1359 }
1360
1361 static void
1362 test_return_on_cancel_atomic (void)
1363 {
1364   GTask *task;
1365   GCancellable *cancellable;
1366   volatile gint state;
1367   gboolean callback_ran;
1368
1369   cancellable = g_cancellable_new ();
1370   g_mutex_lock (&roca_mutex_1);
1371   g_mutex_lock (&roca_mutex_2);
1372
1373   /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1374   state = 0;
1375   callback_ran = FALSE;
1376   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1377   g_task_set_return_on_cancel (task, TRUE);
1378
1379   g_task_set_task_data (task, (gpointer)&state, NULL);
1380   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1381   g_object_unref (task);
1382
1383   g_assert_cmpint (state, ==, 0);
1384
1385   while (state == 0)
1386     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1387   g_assert (state == 1);
1388
1389   while (state == 1)
1390     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1391   g_assert (state == 2);
1392
1393   while (state == 2)
1394     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1395   g_assert (state == 4);
1396
1397   while (state == 4)
1398     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1399   g_assert (state == 6);
1400
1401   /* callback assumes there'll be a cancelled error */
1402   g_cancellable_cancel (cancellable);
1403
1404   g_assert (callback_ran == FALSE);
1405   g_main_loop_run (loop);
1406   g_assert (callback_ran == TRUE);
1407
1408   g_cancellable_reset (cancellable);
1409
1410
1411   /* If we cancel while it's temporarily not return-on-cancel, the
1412    * task won't complete right away, and further
1413    * g_task_set_return_on_cancel() calls will return FALSE.
1414    */
1415   state = 0;
1416   callback_ran = FALSE;
1417   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1418   g_task_set_return_on_cancel (task, TRUE);
1419
1420   g_task_set_task_data (task, (gpointer)&state, NULL);
1421   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1422   g_object_unref (task);
1423
1424   g_assert_cmpint (state, ==, 0);
1425
1426   while (state == 0)
1427     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1428   g_assert (state == 1);
1429   g_assert (g_task_get_return_on_cancel (task));
1430
1431   while (state == 1)
1432     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1433   g_assert (state == 2);
1434   g_assert (!g_task_get_return_on_cancel (task));
1435
1436   g_cancellable_cancel (cancellable);
1437   g_idle_add (idle_quit_loop, NULL);
1438   g_main_loop_run (loop);
1439   g_assert (callback_ran == FALSE);
1440
1441   while (state == 2)
1442     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1443   g_assert (state == 5);
1444   g_assert (!g_task_get_return_on_cancel (task));
1445
1446   g_main_loop_run (loop);
1447   g_assert (callback_ran == TRUE);
1448
1449   while (state == 5)
1450     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1451   g_assert (state == 7);
1452
1453   g_object_unref (cancellable);
1454   g_mutex_unlock (&roca_mutex_1);
1455   g_mutex_unlock (&roca_mutex_2);
1456 }
1457
1458 /* test_return_pointer: memory management of pointer returns */
1459
1460 static void
1461 test_return_pointer (void)
1462 {
1463   GObject *object, *ret;
1464   GTask *task;
1465   GCancellable *cancellable;
1466   GError *error = NULL;
1467
1468   /* If we don't read back the return value, the task will
1469    * run its destroy notify.
1470    */
1471   object = (GObject *)g_dummy_object_new ();
1472   g_assert_cmpint (object->ref_count, ==, 1);
1473   g_object_add_weak_pointer (object, (gpointer *)&object);
1474
1475   task = g_task_new (NULL, NULL, NULL, NULL);
1476   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1477   g_task_return_pointer (task, object, g_object_unref);
1478   g_assert_cmpint (object->ref_count, ==, 1);
1479
1480   g_object_unref (task);
1481   g_assert (task == NULL);
1482   g_assert (object == NULL);
1483
1484   /* Likewise, if the return value is overwritten by an error */
1485   object = (GObject *)g_dummy_object_new ();
1486   g_assert_cmpint (object->ref_count, ==, 1);
1487   g_object_add_weak_pointer (object, (gpointer *)&object);
1488
1489   cancellable = g_cancellable_new ();
1490   task = g_task_new (NULL, cancellable, NULL, NULL);
1491   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1492   g_task_return_pointer (task, object, g_object_unref);
1493   g_assert_cmpint (object->ref_count, ==, 1);
1494   g_cancellable_cancel (cancellable);
1495   g_assert_cmpint (object->ref_count, ==, 1);
1496
1497   ret = g_task_propagate_pointer (task, &error);
1498   g_assert (ret == NULL);
1499   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1500   g_clear_error (&error);
1501   g_assert_cmpint (object->ref_count, ==, 1);
1502
1503   g_object_unref (task);
1504   g_object_unref (cancellable);
1505   g_assert (task == NULL);
1506   g_assert (object == NULL);
1507   
1508   /* If we read back the return value, we steal its ref */
1509   object = (GObject *)g_dummy_object_new ();
1510   g_assert_cmpint (object->ref_count, ==, 1);
1511   g_object_add_weak_pointer (object, (gpointer *)&object);
1512
1513   task = g_task_new (NULL, NULL, NULL, NULL);
1514   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1515   g_task_return_pointer (task, object, g_object_unref);
1516   g_assert_cmpint (object->ref_count, ==, 1);
1517
1518   ret = g_task_propagate_pointer (task, &error);
1519   g_assert_no_error (error);
1520   g_assert (ret == object);
1521   g_assert_cmpint (object->ref_count, ==, 1);
1522
1523   g_object_unref (task);
1524   g_assert (task == NULL);
1525   g_assert_cmpint (object->ref_count, ==, 1);
1526   g_object_unref (object);
1527   g_assert (object == NULL);
1528 }
1529
1530 /* test_object_keepalive: GTask takes a ref on its source object */
1531
1532 static GObject *keepalive_object;
1533
1534 static void
1535 keepalive_callback (GObject      *object,
1536                     GAsyncResult *result,
1537                     gpointer      user_data)
1538 {
1539   gssize *result_out = user_data;
1540   GError *error = NULL;
1541
1542   g_assert (object == keepalive_object);
1543   g_assert (g_task_is_valid (result, object));
1544   g_assert (g_async_result_get_user_data (result) == user_data);
1545   g_assert (!g_task_had_error (G_TASK (result)));
1546
1547   *result_out = g_task_propagate_int (G_TASK (result), &error);
1548   g_assert_no_error (error);
1549
1550   g_main_loop_quit (loop);
1551 }
1552
1553 static void
1554 test_object_keepalive (void)
1555 {
1556   GObject *object;
1557   GTask *task;
1558   gssize result;
1559   int ref_count;
1560
1561   keepalive_object = object = (GObject *)g_dummy_object_new ();
1562   g_object_add_weak_pointer (object, (gpointer *)&object);
1563
1564   task = g_task_new (object, NULL, keepalive_callback, &result);
1565   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1566
1567   ref_count = object->ref_count;
1568   g_assert_cmpint (ref_count, >, 1);
1569
1570   g_assert (g_task_get_source_object (task) == object);
1571   g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
1572   g_assert_cmpint (object->ref_count, ==, ref_count + 1);
1573   g_object_unref (object);
1574
1575   g_object_unref (object);
1576   g_assert (object != NULL);
1577
1578   g_task_return_int (task, magic);
1579   g_main_loop_run (loop);
1580
1581   g_assert (object != NULL);
1582   g_assert_cmpint (result, ==, magic);
1583
1584   g_object_unref (task);
1585   g_assert (task == NULL);
1586   g_assert (object == NULL);
1587 }
1588
1589 /* test_legacy_error: legacy GSimpleAsyncResult handling */
1590 static void test_legacy_error (void);
1591
1592 static void
1593 legacy_error_callback (GObject      *object,
1594                        GAsyncResult *result,
1595                        gpointer      user_data)
1596 {
1597   gssize *result_out = user_data;
1598   GError *error = NULL;
1599
1600   g_assert (object == NULL);
1601   g_assert (g_async_result_is_tagged (result, test_legacy_error));
1602   g_assert (g_async_result_get_user_data (result) == user_data);
1603
1604   if (g_async_result_legacy_propagate_error (result, &error))
1605     {
1606       g_assert (!g_task_is_valid (result, object));
1607       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1608       g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
1609       G_GNUC_END_IGNORE_DEPRECATIONS;
1610
1611       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1612       *result_out = -2;
1613     }
1614   else
1615     {
1616       g_assert (g_task_is_valid (result, object));
1617
1618       *result_out = g_task_propagate_int (G_TASK (result), NULL);
1619       /* Might be error, might not */
1620     }
1621
1622   g_main_loop_quit (loop);
1623 }
1624
1625 static gboolean
1626 legacy_error_return (gpointer user_data)
1627 {
1628   if (G_IS_TASK (user_data))
1629     {
1630       GTask *task = user_data;
1631
1632       g_task_return_int (task, magic);
1633       g_object_unref (task);
1634     }
1635   else
1636     {
1637       GSimpleAsyncResult *simple = user_data;
1638
1639       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1640       g_simple_async_result_set_error (simple,
1641                                        G_IO_ERROR,
1642                                        G_IO_ERROR_FAILED,
1643                                        "Failed");
1644       g_simple_async_result_complete (simple);
1645       G_GNUC_END_IGNORE_DEPRECATIONS;
1646       g_object_unref (simple);
1647     }
1648
1649   return FALSE;
1650 }
1651
1652 static void
1653 test_legacy_error (void)
1654 {
1655   GTask *task;
1656   GSimpleAsyncResult *simple;
1657   gssize result;
1658
1659   /* GTask success */
1660   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1661   g_task_set_source_tag (task, test_legacy_error);
1662   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1663
1664   g_idle_add (legacy_error_return, task);
1665   g_main_loop_run (loop);
1666
1667   g_assert_cmpint (result, ==, magic);
1668   g_assert (task == NULL);
1669
1670   /* GTask error */
1671   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1672   g_task_set_source_tag (task, test_legacy_error);
1673   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1674
1675   g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
1676                            "Failed");
1677   g_object_unref (task);
1678   g_main_loop_run (loop);
1679
1680   g_assert_cmpint (result, ==, -1);
1681   g_assert (task == NULL);
1682
1683   /* GSimpleAsyncResult error */
1684   G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1685   simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
1686                                       test_legacy_error);
1687   G_GNUC_END_IGNORE_DEPRECATIONS;
1688   g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
1689
1690   g_idle_add (legacy_error_return, simple);
1691   g_main_loop_run (loop);
1692
1693   g_assert_cmpint (result, ==, -2);
1694   g_assert (simple == NULL);
1695 }
1696
1697
1698 int
1699 main (int argc, char **argv)
1700 {
1701   int ret;
1702
1703   g_test_init (&argc, &argv, NULL);
1704
1705   loop = g_main_loop_new (NULL, FALSE);
1706   main_thread = g_thread_self ();
1707   magic = g_get_monotonic_time ();
1708
1709   g_test_add_func ("/gtask/basic", test_basic);
1710   g_test_add_func ("/gtask/error", test_error);
1711   g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
1712   g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
1713   g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
1714   g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
1715   g_test_add_func ("/gtask/no-callback", test_no_callback);
1716   g_test_add_func ("/gtask/report-error", test_report_error);
1717   g_test_add_func ("/gtask/priority", test_priority);
1718   g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
1719   g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
1720   g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
1721   g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
1722   g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
1723   g_test_add_func ("/gtask/run-in-thread-nested", test_run_in_thread_nested);
1724   g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
1725   g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
1726   g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
1727   g_test_add_func ("/gtask/return-pointer", test_return_pointer);
1728   g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
1729   g_test_add_func ("/gtask/legacy-error", test_legacy_error);
1730
1731   ret = g_test_run();
1732
1733   g_main_loop_unref (loop);
1734
1735   return ret;
1736 }