[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[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 GMutex run_in_thread_mutex;
655 static GCond run_in_thread_cond;
656
657 static void
658 task_weak_notify (gpointer  user_data,
659                   GObject  *ex_task)
660 {
661   gboolean *weak_notify_ran = user_data;
662
663   g_mutex_lock (&run_in_thread_mutex);
664   *weak_notify_ran = TRUE;
665   g_cond_signal (&run_in_thread_cond);
666   g_mutex_unlock (&run_in_thread_mutex);
667 }
668
669 static void
670 run_in_thread_callback (GObject      *object,
671                         GAsyncResult *result,
672                         gpointer      user_data)
673 {
674   gboolean *done = user_data;
675   GError *error = NULL;
676   gssize ret;
677
678   g_assert (g_thread_self () == main_thread);
679
680   g_assert (object == NULL);
681   g_assert (g_task_is_valid (result, object));
682   g_assert (g_async_result_get_user_data (result) == user_data);
683   g_assert (!g_task_had_error (G_TASK (result)));
684
685   ret = g_task_propagate_int (G_TASK (result), &error);
686   g_assert_no_error (error);
687   g_assert_cmpint (ret, ==, magic);
688
689   *done = TRUE;
690   g_main_loop_quit (loop);
691 }
692
693 static void
694 run_in_thread_thread (GTask        *task,
695                       gpointer      source_object,
696                       gpointer      task_data,
697                       GCancellable *cancellable)
698 {
699   gboolean *thread_ran = task_data;
700
701   g_assert (source_object == g_task_get_source_object (task));
702   g_assert (task_data == g_task_get_task_data (task));
703   g_assert (cancellable == g_task_get_cancellable (task));
704
705   g_assert (g_thread_self () != main_thread);
706
707   g_mutex_lock (&run_in_thread_mutex);
708   *thread_ran = TRUE;
709   g_cond_signal (&run_in_thread_cond);
710   g_mutex_unlock (&run_in_thread_mutex);
711
712   g_task_return_int (task, magic);
713 }
714
715 static void
716 test_run_in_thread (void)
717 {
718   GTask *task;
719   volatile gboolean thread_ran = FALSE;
720   volatile gboolean weak_notify_ran = FALSE;
721   gboolean done = FALSE;
722
723   task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
724   g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
725
726   g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
727   g_task_run_in_thread (task, run_in_thread_thread);
728   g_object_unref (task);
729
730   g_mutex_lock (&run_in_thread_mutex);
731   while (!thread_ran)
732     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
733   g_mutex_unlock (&run_in_thread_mutex);
734
735   g_assert (done == FALSE);
736   g_assert (weak_notify_ran == FALSE);
737
738   g_main_loop_run (loop);
739
740   g_assert (done == TRUE);
741
742   g_mutex_lock (&run_in_thread_mutex);
743   while (!weak_notify_ran)
744     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
745   g_mutex_unlock (&run_in_thread_mutex);
746 }
747
748 /* test_run_in_thread_sync */
749
750 static void
751 run_in_thread_sync_callback (GObject      *object,
752                              GAsyncResult *result,
753                              gpointer      user_data)
754 {
755   /* g_task_run_in_thread_sync() does not invoke the task's callback */
756   g_assert_not_reached ();
757 }
758
759 static void
760 run_in_thread_sync_thread (GTask        *task,
761                            gpointer      source_object,
762                            gpointer      task_data,
763                            GCancellable *cancellable)
764 {
765   gboolean *thread_ran = task_data;
766
767   g_assert (source_object == g_task_get_source_object (task));
768   g_assert (task_data == g_task_get_task_data (task));
769   g_assert (cancellable == g_task_get_cancellable (task));
770
771   g_assert (g_thread_self () != main_thread);
772
773   *thread_ran = TRUE;
774   g_task_return_int (task, magic);
775 }
776
777 static void
778 test_run_in_thread_sync (void)
779 {
780   GTask *task;
781   gboolean thread_ran = FALSE;
782   gssize ret;
783   GError *error = NULL;
784
785   task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
786
787   g_task_set_task_data (task, &thread_ran, NULL);
788   g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
789
790   g_assert (thread_ran == TRUE);
791   g_assert (task != NULL);
792   g_assert (!g_task_had_error (task));
793
794   ret = g_task_propagate_int (task, &error);
795   g_assert_no_error (error);
796   g_assert_cmpint (ret, ==, magic);
797
798   g_object_unref (task);
799 }
800
801 /* test_run_in_thread_priority */
802
803 static GMutex fake_task_mutex, last_fake_task_mutex;
804 static gint sequence_number = 0;
805
806 static void
807 quit_main_loop_callback (GObject      *object,
808                          GAsyncResult *result,
809                          gpointer      user_data)
810 {
811   GError *error = NULL;
812   gboolean ret;
813
814   g_assert (g_thread_self () == main_thread);
815
816   g_assert (object == NULL);
817   g_assert (g_task_is_valid (result, object));
818   g_assert (g_async_result_get_user_data (result) == user_data);
819   g_assert (!g_task_had_error (G_TASK (result)));
820
821   ret = g_task_propagate_boolean (G_TASK (result), &error);
822   g_assert_no_error (error);
823   g_assert_cmpint (ret, ==, TRUE);
824
825   g_main_loop_quit (loop);
826 }
827
828 static void
829 set_sequence_number_thread (GTask        *task,
830                             gpointer      source_object,
831                             gpointer      task_data,
832                             GCancellable *cancellable)
833 {
834   gint *seq_no_p = task_data;
835
836   *seq_no_p = ++sequence_number;
837   g_task_return_boolean (task, TRUE);
838 }
839
840 static void
841 fake_task_thread (GTask        *task,
842                   gpointer      source_object,
843                   gpointer      task_data,
844                   GCancellable *cancellable)
845 {
846   GMutex *mutex = task_data;
847
848   g_mutex_lock (mutex);
849   g_mutex_unlock (mutex);
850   g_task_return_boolean (task, TRUE);
851 }
852
853 #define G_TASK_THREAD_POOL_SIZE 10
854 static int fake_tasks_running;
855
856 static void
857 fake_task_callback (GObject      *source,
858                     GAsyncResult *result,
859                     gpointer      user_data)
860 {
861   if (--fake_tasks_running == 0)
862     g_main_loop_quit (loop);
863 }
864
865 static void
866 clog_up_thread_pool (void)
867 {
868   GTask *task;
869   int i;
870
871   g_thread_pool_stop_unused_threads ();
872
873   g_mutex_lock (&fake_task_mutex);
874   for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
875     {
876       task = g_task_new (NULL, NULL, fake_task_callback, NULL);
877       g_task_set_task_data (task, &fake_task_mutex, NULL);
878       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
879       g_task_set_priority (task, G_PRIORITY_HIGH * 2);
880       g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
881       g_task_run_in_thread (task, fake_task_thread);
882       g_object_unref (task);
883       fake_tasks_running++;
884     }
885
886   g_mutex_lock (&last_fake_task_mutex);
887   task = g_task_new (NULL, NULL, NULL, NULL);
888   g_task_set_task_data (task, &last_fake_task_mutex, NULL);
889   g_task_set_priority (task, G_PRIORITY_HIGH * 2);
890   g_task_run_in_thread (task, fake_task_thread);
891   g_object_unref (task);
892 }
893
894 static void
895 unclog_thread_pool (void)
896 {
897   g_mutex_unlock (&fake_task_mutex);
898   g_main_loop_run (loop);
899 }
900
901 static void
902 test_run_in_thread_priority (void)
903 {
904   GTask *task;
905   GCancellable *cancellable;
906   int seq_a, seq_b, seq_c, seq_d;
907
908   clog_up_thread_pool ();
909
910   /* Queue three more tasks that we'll arrange to have run serially */
911   task = g_task_new (NULL, NULL, NULL, NULL);
912   g_task_set_task_data (task, &seq_a, NULL);
913   g_task_run_in_thread (task, set_sequence_number_thread);
914   g_object_unref (task);
915   
916   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
917   g_task_set_task_data (task, &seq_b, NULL);
918   g_task_set_priority (task, G_PRIORITY_LOW);
919   g_task_run_in_thread (task, set_sequence_number_thread);
920   g_object_unref (task);
921   
922   task = g_task_new (NULL, NULL, NULL, NULL);
923   g_task_set_task_data (task, &seq_c, NULL);
924   g_task_set_priority (task, G_PRIORITY_HIGH);
925   g_task_run_in_thread (task, set_sequence_number_thread);
926   g_object_unref (task);
927   
928   cancellable = g_cancellable_new ();
929   task = g_task_new (NULL, cancellable, NULL, NULL);
930   g_task_set_task_data (task, &seq_d, NULL);
931   g_task_run_in_thread (task, set_sequence_number_thread);
932   g_cancellable_cancel (cancellable);
933   g_object_unref (cancellable);
934   g_object_unref (task);
935
936   /* Let the last fake task complete; the four other tasks will then
937    * complete serially, in the order D, C, A, B, and B will quit the
938    * main loop.
939    */
940   g_mutex_unlock (&last_fake_task_mutex);
941   g_main_loop_run (loop);
942
943   g_assert_cmpint (seq_d, ==, 1);
944   g_assert_cmpint (seq_c, ==, 2);
945   g_assert_cmpint (seq_a, ==, 3);
946   g_assert_cmpint (seq_b, ==, 4);
947
948   unclog_thread_pool ();
949 }
950
951 /* test_run_in_thread_nested: task threads that block waiting on
952  * other task threads will not cause the thread pool to starve.
953  */
954
955 static void
956 run_nested_task_thread (GTask        *task,
957                         gpointer      source_object,
958                         gpointer      task_data,
959                         GCancellable *cancellable)
960 {
961   GTask *nested;
962   int *nested_tasks_left = task_data;
963
964   if ((*nested_tasks_left)--)
965     {
966       nested = g_task_new (NULL, NULL, NULL, NULL);
967       g_task_set_task_data (nested, nested_tasks_left, NULL);
968       g_task_run_in_thread_sync (nested, run_nested_task_thread);
969       g_object_unref (nested);
970     }
971
972   g_task_return_boolean (task, TRUE);
973 }
974
975 static void
976 test_run_in_thread_nested (void)
977 {
978   GTask *task;
979   int nested_tasks_left = 2;
980
981   clog_up_thread_pool ();
982
983   task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
984   g_task_set_task_data (task, &nested_tasks_left, NULL);
985   g_task_run_in_thread (task, run_nested_task_thread);
986   g_object_unref (task);
987
988   g_mutex_unlock (&last_fake_task_mutex);
989   g_main_loop_run (loop);
990
991   unclog_thread_pool ();
992 }
993
994 /* test_return_on_cancel */
995
996 GMutex roc_init_mutex, roc_finish_mutex;
997 GCond roc_init_cond, roc_finish_cond;
998
999 typedef enum {
1000   THREAD_STARTING,
1001   THREAD_RUNNING,
1002   THREAD_CANCELLED,
1003   THREAD_COMPLETED
1004 } ThreadState;
1005
1006 static void
1007 return_on_cancel_callback (GObject      *object,
1008                            GAsyncResult *result,
1009                            gpointer      user_data)
1010 {
1011   gboolean *callback_ran = user_data;
1012   GError *error = NULL;
1013   gssize ret;
1014
1015   g_assert (g_thread_self () == main_thread);
1016
1017   g_assert (object == NULL);
1018   g_assert (g_task_is_valid (result, object));
1019   g_assert (g_async_result_get_user_data (result) == user_data);
1020   g_assert (g_task_had_error (G_TASK (result)));
1021
1022   ret = g_task_propagate_int (G_TASK (result), &error);
1023   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1024   g_clear_error (&error);
1025   g_assert_cmpint (ret, ==, -1);
1026
1027   *callback_ran = TRUE;
1028   g_main_loop_quit (loop);
1029 }
1030
1031 static void
1032 return_on_cancel_thread (GTask        *task,
1033                          gpointer      source_object,
1034                          gpointer      task_data,
1035                          GCancellable *cancellable)
1036 {
1037   ThreadState *state = task_data;
1038
1039   g_assert (source_object == g_task_get_source_object (task));
1040   g_assert (task_data == g_task_get_task_data (task));
1041   g_assert (cancellable == g_task_get_cancellable (task));
1042
1043   g_assert (g_thread_self () != main_thread);
1044
1045   g_mutex_lock (&roc_init_mutex);
1046   *state = THREAD_RUNNING;
1047   g_cond_signal (&roc_init_cond);
1048   g_mutex_unlock (&roc_init_mutex);
1049
1050   g_mutex_lock (&roc_finish_mutex);
1051
1052   if (!g_task_get_return_on_cancel (task) ||
1053       g_task_set_return_on_cancel (task, FALSE))
1054     {
1055       *state = THREAD_COMPLETED;
1056       g_task_return_int (task, magic);
1057     }
1058   else
1059     *state = THREAD_CANCELLED;
1060
1061   g_cond_signal (&roc_finish_cond);
1062   g_mutex_unlock (&roc_finish_mutex);
1063 }
1064
1065 static void
1066 test_return_on_cancel (void)
1067 {
1068   GTask *task;
1069   GCancellable *cancellable;
1070   volatile ThreadState thread_state;
1071   volatile gboolean weak_notify_ran = FALSE;
1072   gboolean callback_ran;
1073
1074   cancellable = g_cancellable_new ();
1075
1076   /* If return-on-cancel is FALSE (default), the task does not return
1077    * early.
1078    */
1079   callback_ran = FALSE;
1080   thread_state = THREAD_STARTING;
1081   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1082
1083   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1084   g_mutex_lock (&roc_init_mutex);
1085   g_mutex_lock (&roc_finish_mutex);
1086   g_task_run_in_thread (task, return_on_cancel_thread);
1087   g_object_unref (task);
1088
1089   while (thread_state == THREAD_STARTING)
1090     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1091   g_mutex_unlock (&roc_init_mutex);
1092
1093   g_assert (thread_state == THREAD_RUNNING);
1094   g_assert (callback_ran == FALSE);
1095
1096   g_cancellable_cancel (cancellable);
1097   g_mutex_unlock (&roc_finish_mutex);
1098   g_main_loop_run (loop);
1099
1100   g_assert (thread_state == THREAD_COMPLETED);
1101   g_assert (callback_ran == TRUE);
1102
1103   g_cancellable_reset (cancellable);
1104
1105   /* If return-on-cancel is TRUE, it does return early */
1106   callback_ran = FALSE;
1107   thread_state = THREAD_STARTING;
1108   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1109   g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
1110   g_task_set_return_on_cancel (task, TRUE);
1111
1112   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1113   g_mutex_lock (&roc_init_mutex);
1114   g_mutex_lock (&roc_finish_mutex);
1115   g_task_run_in_thread (task, return_on_cancel_thread);
1116   g_object_unref (task);
1117
1118   while (thread_state == THREAD_STARTING)
1119     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1120   g_mutex_unlock (&roc_init_mutex);
1121
1122   g_assert (thread_state == THREAD_RUNNING);
1123   g_assert (callback_ran == FALSE);
1124
1125   g_cancellable_cancel (cancellable);
1126   g_main_loop_run (loop);
1127   g_assert (thread_state == THREAD_RUNNING);
1128   g_assert (callback_ran == TRUE);
1129
1130   g_assert (weak_notify_ran == FALSE);
1131
1132   while (thread_state == THREAD_RUNNING)
1133     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1134   g_mutex_unlock (&roc_finish_mutex);
1135
1136   g_assert (thread_state == THREAD_CANCELLED);
1137   g_mutex_lock (&run_in_thread_mutex);
1138   while (!weak_notify_ran)
1139     g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
1140   g_mutex_unlock (&run_in_thread_mutex);
1141
1142   g_cancellable_reset (cancellable);
1143
1144   /* If the task is already cancelled before it starts, it returns
1145    * immediately, but the thread func still runs.
1146    */
1147   callback_ran = FALSE;
1148   thread_state = THREAD_STARTING;
1149   task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1150   g_task_set_return_on_cancel (task, TRUE);
1151
1152   g_cancellable_cancel (cancellable);
1153
1154   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1155   g_mutex_lock (&roc_init_mutex);
1156   g_mutex_lock (&roc_finish_mutex);
1157   g_task_run_in_thread (task, return_on_cancel_thread);
1158   g_object_unref (task);
1159
1160   g_main_loop_run (loop);
1161   g_assert (callback_ran == TRUE);
1162
1163   while (thread_state == THREAD_STARTING)
1164     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1165   g_mutex_unlock (&roc_init_mutex);
1166
1167   g_assert (thread_state == THREAD_RUNNING);
1168
1169   while (thread_state == THREAD_RUNNING)
1170     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1171   g_mutex_unlock (&roc_finish_mutex);
1172
1173   g_assert (thread_state == THREAD_CANCELLED);
1174
1175   g_object_unref (cancellable);
1176 }
1177
1178 /* test_return_on_cancel_sync */
1179
1180 static gpointer
1181 cancel_sync_runner_thread (gpointer task)
1182 {
1183   g_task_run_in_thread_sync (task, return_on_cancel_thread);
1184   return NULL;
1185 }
1186
1187 static void
1188 test_return_on_cancel_sync (void)
1189 {
1190   GTask *task;
1191   GCancellable *cancellable;
1192   volatile ThreadState thread_state;
1193   GThread *runner_thread;
1194   gssize ret;
1195   GError *error = NULL;
1196
1197   cancellable = g_cancellable_new ();
1198
1199   /* If return-on-cancel is FALSE, the task does not return early.
1200    */
1201   thread_state = THREAD_STARTING;
1202   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
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_mutex_unlock (&roc_finish_mutex);
1218   g_thread_join (runner_thread);
1219   g_assert (thread_state == THREAD_COMPLETED);
1220
1221   ret = g_task_propagate_int (task, &error);
1222   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1223   g_clear_error (&error);
1224   g_assert_cmpint (ret, ==, -1);
1225
1226   g_object_unref (task);
1227
1228   g_cancellable_reset (cancellable);
1229
1230   /* If return-on-cancel is TRUE, it does return early */
1231   thread_state = THREAD_STARTING;
1232   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1233   g_task_set_return_on_cancel (task, TRUE);
1234
1235   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1236   g_mutex_lock (&roc_init_mutex);
1237   g_mutex_lock (&roc_finish_mutex);
1238   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1239                                 cancel_sync_runner_thread, task);
1240
1241   while (thread_state == THREAD_STARTING)
1242     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1243   g_mutex_unlock (&roc_init_mutex);
1244
1245   g_assert (thread_state == THREAD_RUNNING);
1246
1247   g_cancellable_cancel (cancellable);
1248   g_thread_join (runner_thread);
1249   g_assert (thread_state == THREAD_RUNNING);
1250
1251   ret = g_task_propagate_int (task, &error);
1252   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1253   g_clear_error (&error);
1254   g_assert_cmpint (ret, ==, -1);
1255
1256   g_object_unref (task);
1257
1258   while (thread_state == THREAD_RUNNING)
1259     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1260   g_mutex_unlock (&roc_finish_mutex);
1261
1262   g_assert (thread_state == THREAD_CANCELLED);
1263
1264   g_cancellable_reset (cancellable);
1265
1266   /* If the task is already cancelled before it starts, it returns
1267    * immediately, but the thread func still runs.
1268    */
1269   thread_state = THREAD_STARTING;
1270   task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1271   g_task_set_return_on_cancel (task, TRUE);
1272
1273   g_cancellable_cancel (cancellable);
1274
1275   g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1276   g_mutex_lock (&roc_init_mutex);
1277   g_mutex_lock (&roc_finish_mutex);
1278   runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1279                                 cancel_sync_runner_thread, task);
1280
1281   g_thread_join (runner_thread);
1282   g_assert (thread_state == THREAD_STARTING);
1283
1284   ret = g_task_propagate_int (task, &error);
1285   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1286   g_clear_error (&error);
1287   g_assert_cmpint (ret, ==, -1);
1288
1289   g_object_unref (task);
1290
1291   while (thread_state == THREAD_STARTING)
1292     g_cond_wait (&roc_init_cond, &roc_init_mutex);
1293   g_mutex_unlock (&roc_init_mutex);
1294
1295   g_assert (thread_state == THREAD_RUNNING);
1296
1297   while (thread_state == THREAD_RUNNING)
1298     g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1299   g_mutex_unlock (&roc_finish_mutex);
1300
1301   g_assert (thread_state == THREAD_CANCELLED);
1302
1303   g_object_unref (cancellable);
1304 }
1305
1306 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1307  * non-racy
1308  */
1309
1310 GMutex roca_mutex_1, roca_mutex_2;
1311 GCond roca_cond_1, roca_cond_2;
1312
1313 static void
1314 return_on_cancel_atomic_callback (GObject      *object,
1315                                   GAsyncResult *result,
1316                                   gpointer      user_data)
1317 {
1318   gboolean *callback_ran = user_data;
1319   GError *error = NULL;
1320   gssize ret;
1321
1322   g_assert (g_thread_self () == main_thread);
1323
1324   g_assert (object == NULL);
1325   g_assert (g_task_is_valid (result, object));
1326   g_assert (g_async_result_get_user_data (result) == user_data);
1327   g_assert (g_task_had_error (G_TASK (result)));
1328
1329   ret = g_task_propagate_int (G_TASK (result), &error);
1330   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1331   g_clear_error (&error);
1332   g_assert_cmpint (ret, ==, -1);
1333
1334   *callback_ran = TRUE;
1335   g_main_loop_quit (loop);
1336 }
1337
1338 static gboolean
1339 idle_quit_loop (gpointer user_data)
1340 {
1341   g_main_loop_quit (loop);
1342   return FALSE;
1343 }
1344
1345 static void
1346 return_on_cancel_atomic_thread (GTask        *task,
1347                                 gpointer      source_object,
1348                                 gpointer      task_data,
1349                                 GCancellable *cancellable)
1350 {
1351   gint *state = task_data;
1352
1353   g_assert (source_object == g_task_get_source_object (task));
1354   g_assert (task_data == g_task_get_task_data (task));
1355   g_assert (cancellable == g_task_get_cancellable (task));
1356
1357   g_assert (g_thread_self () != main_thread);
1358   g_assert_cmpint (*state, ==, 0);
1359
1360   g_mutex_lock (&roca_mutex_1);
1361   *state = 1;
1362   g_cond_signal (&roca_cond_1);
1363   g_mutex_unlock (&roca_mutex_1);
1364
1365   g_mutex_lock (&roca_mutex_2);
1366   if (g_task_set_return_on_cancel (task, FALSE))
1367     *state = 2;
1368   else
1369     *state = 3;
1370   g_cond_signal (&roca_cond_2);
1371   g_mutex_unlock (&roca_mutex_2);
1372
1373   g_mutex_lock (&roca_mutex_1);
1374   if (g_task_set_return_on_cancel (task, TRUE))
1375     *state = 4;
1376   else
1377     *state = 5;
1378   g_cond_signal (&roca_cond_1);
1379   g_mutex_unlock (&roca_mutex_1);
1380
1381   g_mutex_lock (&roca_mutex_2);
1382   if (g_task_set_return_on_cancel (task, TRUE))
1383     *state = 6;
1384   else
1385     *state = 7;
1386   g_cond_signal (&roca_cond_2);
1387   g_mutex_unlock (&roca_mutex_2);
1388
1389   g_task_return_int (task, magic);
1390 }
1391
1392 static void
1393 test_return_on_cancel_atomic (void)
1394 {
1395   GTask *task;
1396   GCancellable *cancellable;
1397   volatile gint state;
1398   gboolean callback_ran;
1399
1400   cancellable = g_cancellable_new ();
1401   g_mutex_lock (&roca_mutex_1);
1402   g_mutex_lock (&roca_mutex_2);
1403
1404   /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1405   state = 0;
1406   callback_ran = FALSE;
1407   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1408   g_task_set_return_on_cancel (task, TRUE);
1409
1410   g_task_set_task_data (task, (gpointer)&state, NULL);
1411   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1412   g_object_unref (task);
1413
1414   g_assert_cmpint (state, ==, 0);
1415
1416   while (state == 0)
1417     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1418   g_assert (state == 1);
1419
1420   while (state == 1)
1421     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1422   g_assert (state == 2);
1423
1424   while (state == 2)
1425     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1426   g_assert (state == 4);
1427
1428   while (state == 4)
1429     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1430   g_assert (state == 6);
1431
1432   /* callback assumes there'll be a cancelled error */
1433   g_cancellable_cancel (cancellable);
1434
1435   g_assert (callback_ran == FALSE);
1436   g_main_loop_run (loop);
1437   g_assert (callback_ran == TRUE);
1438
1439   g_cancellable_reset (cancellable);
1440
1441
1442   /* If we cancel while it's temporarily not return-on-cancel, the
1443    * task won't complete right away, and further
1444    * g_task_set_return_on_cancel() calls will return FALSE.
1445    */
1446   state = 0;
1447   callback_ran = FALSE;
1448   task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1449   g_task_set_return_on_cancel (task, TRUE);
1450
1451   g_task_set_task_data (task, (gpointer)&state, NULL);
1452   g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1453   g_object_unref (task);
1454
1455   g_assert_cmpint (state, ==, 0);
1456
1457   while (state == 0)
1458     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1459   g_assert (state == 1);
1460   g_assert (g_task_get_return_on_cancel (task));
1461
1462   while (state == 1)
1463     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1464   g_assert (state == 2);
1465   g_assert (!g_task_get_return_on_cancel (task));
1466
1467   g_cancellable_cancel (cancellable);
1468   g_idle_add (idle_quit_loop, NULL);
1469   g_main_loop_run (loop);
1470   g_assert (callback_ran == FALSE);
1471
1472   while (state == 2)
1473     g_cond_wait (&roca_cond_1, &roca_mutex_1);
1474   g_assert (state == 5);
1475   g_assert (!g_task_get_return_on_cancel (task));
1476
1477   g_main_loop_run (loop);
1478   g_assert (callback_ran == TRUE);
1479
1480   while (state == 5)
1481     g_cond_wait (&roca_cond_2, &roca_mutex_2);
1482   g_assert (state == 7);
1483
1484   g_object_unref (cancellable);
1485   g_mutex_unlock (&roca_mutex_1);
1486   g_mutex_unlock (&roca_mutex_2);
1487 }
1488
1489 /* test_return_pointer: memory management of pointer returns */
1490
1491 static void
1492 test_return_pointer (void)
1493 {
1494   GObject *object, *ret;
1495   GTask *task;
1496   GCancellable *cancellable;
1497   GError *error = NULL;
1498
1499   /* If we don't read back the return value, the task will
1500    * run its destroy notify.
1501    */
1502   object = (GObject *)g_dummy_object_new ();
1503   g_assert_cmpint (object->ref_count, ==, 1);
1504   g_object_add_weak_pointer (object, (gpointer *)&object);
1505
1506   task = g_task_new (NULL, NULL, NULL, NULL);
1507   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1508   g_task_return_pointer (task, object, g_object_unref);
1509   g_assert_cmpint (object->ref_count, ==, 1);
1510
1511   g_object_unref (task);
1512   g_assert (task == NULL);
1513   g_assert (object == NULL);
1514
1515   /* Likewise, if the return value is overwritten by an error */
1516   object = (GObject *)g_dummy_object_new ();
1517   g_assert_cmpint (object->ref_count, ==, 1);
1518   g_object_add_weak_pointer (object, (gpointer *)&object);
1519
1520   cancellable = g_cancellable_new ();
1521   task = g_task_new (NULL, cancellable, NULL, NULL);
1522   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1523   g_task_return_pointer (task, object, g_object_unref);
1524   g_assert_cmpint (object->ref_count, ==, 1);
1525   g_cancellable_cancel (cancellable);
1526   g_assert_cmpint (object->ref_count, ==, 1);
1527
1528   ret = g_task_propagate_pointer (task, &error);
1529   g_assert (ret == NULL);
1530   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1531   g_clear_error (&error);
1532   g_assert_cmpint (object->ref_count, ==, 1);
1533
1534   g_object_unref (task);
1535   g_object_unref (cancellable);
1536   g_assert (task == NULL);
1537   g_assert (object == NULL);
1538   
1539   /* If we read back the return value, we steal its ref */
1540   object = (GObject *)g_dummy_object_new ();
1541   g_assert_cmpint (object->ref_count, ==, 1);
1542   g_object_add_weak_pointer (object, (gpointer *)&object);
1543
1544   task = g_task_new (NULL, NULL, NULL, NULL);
1545   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1546   g_task_return_pointer (task, object, g_object_unref);
1547   g_assert_cmpint (object->ref_count, ==, 1);
1548
1549   ret = g_task_propagate_pointer (task, &error);
1550   g_assert_no_error (error);
1551   g_assert (ret == object);
1552   g_assert_cmpint (object->ref_count, ==, 1);
1553
1554   g_object_unref (task);
1555   g_assert (task == NULL);
1556   g_assert_cmpint (object->ref_count, ==, 1);
1557   g_object_unref (object);
1558   g_assert (object == NULL);
1559 }
1560
1561 /* test_object_keepalive: GTask takes a ref on its source object */
1562
1563 static GObject *keepalive_object;
1564
1565 static void
1566 keepalive_callback (GObject      *object,
1567                     GAsyncResult *result,
1568                     gpointer      user_data)
1569 {
1570   gssize *result_out = user_data;
1571   GError *error = NULL;
1572
1573   g_assert (object == keepalive_object);
1574   g_assert (g_task_is_valid (result, object));
1575   g_assert (g_async_result_get_user_data (result) == user_data);
1576   g_assert (!g_task_had_error (G_TASK (result)));
1577
1578   *result_out = g_task_propagate_int (G_TASK (result), &error);
1579   g_assert_no_error (error);
1580
1581   g_main_loop_quit (loop);
1582 }
1583
1584 static void
1585 test_object_keepalive (void)
1586 {
1587   GObject *object;
1588   GTask *task;
1589   gssize result;
1590   int ref_count;
1591
1592   keepalive_object = object = (GObject *)g_dummy_object_new ();
1593   g_object_add_weak_pointer (object, (gpointer *)&object);
1594
1595   task = g_task_new (object, NULL, keepalive_callback, &result);
1596   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1597
1598   ref_count = object->ref_count;
1599   g_assert_cmpint (ref_count, >, 1);
1600
1601   g_assert (g_task_get_source_object (task) == object);
1602   g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
1603   g_assert_cmpint (object->ref_count, ==, ref_count + 1);
1604   g_object_unref (object);
1605
1606   g_object_unref (object);
1607   g_assert (object != NULL);
1608
1609   g_task_return_int (task, magic);
1610   g_main_loop_run (loop);
1611
1612   g_assert (object != NULL);
1613   g_assert_cmpint (result, ==, magic);
1614
1615   g_object_unref (task);
1616   g_assert (task == NULL);
1617   g_assert (object == NULL);
1618 }
1619
1620 /* test_legacy_error: legacy GSimpleAsyncResult handling */
1621 static void test_legacy_error (void);
1622
1623 static void
1624 legacy_error_callback (GObject      *object,
1625                        GAsyncResult *result,
1626                        gpointer      user_data)
1627 {
1628   gssize *result_out = user_data;
1629   GError *error = NULL;
1630
1631   g_assert (object == NULL);
1632   g_assert (g_async_result_is_tagged (result, test_legacy_error));
1633   g_assert (g_async_result_get_user_data (result) == user_data);
1634
1635   if (g_async_result_legacy_propagate_error (result, &error))
1636     {
1637       g_assert (!g_task_is_valid (result, object));
1638       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1639       g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
1640       G_GNUC_END_IGNORE_DEPRECATIONS;
1641
1642       g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1643       *result_out = -2;
1644     }
1645   else
1646     {
1647       g_assert (g_task_is_valid (result, object));
1648
1649       *result_out = g_task_propagate_int (G_TASK (result), NULL);
1650       /* Might be error, might not */
1651     }
1652
1653   g_main_loop_quit (loop);
1654 }
1655
1656 static gboolean
1657 legacy_error_return (gpointer user_data)
1658 {
1659   if (G_IS_TASK (user_data))
1660     {
1661       GTask *task = user_data;
1662
1663       g_task_return_int (task, magic);
1664       g_object_unref (task);
1665     }
1666   else
1667     {
1668       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
1669
1670       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1671       g_simple_async_result_set_error (simple,
1672                                        G_IO_ERROR,
1673                                        G_IO_ERROR_FAILED,
1674                                        "Failed");
1675       g_simple_async_result_complete (simple);
1676       G_GNUC_END_IGNORE_DEPRECATIONS;
1677       g_object_unref (simple);
1678     }
1679
1680   return FALSE;
1681 }
1682
1683 static void
1684 test_legacy_error (void)
1685 {
1686   GTask *task;
1687   GSimpleAsyncResult *simple;
1688   gssize result;
1689
1690   /* GTask success */
1691   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1692   g_task_set_source_tag (task, test_legacy_error);
1693   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1694
1695   g_idle_add (legacy_error_return, task);
1696   g_main_loop_run (loop);
1697
1698   g_assert_cmpint (result, ==, magic);
1699   g_assert (task == NULL);
1700
1701   /* GTask error */
1702   task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1703   g_task_set_source_tag (task, test_legacy_error);
1704   g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1705
1706   g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
1707                            "Failed");
1708   g_object_unref (task);
1709   g_main_loop_run (loop);
1710
1711   g_assert_cmpint (result, ==, -1);
1712   g_assert (task == NULL);
1713
1714   /* GSimpleAsyncResult error */
1715   G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1716   simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
1717                                       test_legacy_error);
1718   G_GNUC_END_IGNORE_DEPRECATIONS;
1719   g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
1720
1721   g_idle_add (legacy_error_return, simple);
1722   g_main_loop_run (loop);
1723
1724   g_assert_cmpint (result, ==, -2);
1725   g_assert (simple == NULL);
1726 }
1727
1728
1729 int
1730 main (int argc, char **argv)
1731 {
1732   int ret;
1733
1734   g_test_init (&argc, &argv, NULL);
1735
1736   loop = g_main_loop_new (NULL, FALSE);
1737   main_thread = g_thread_self ();
1738   magic = g_get_monotonic_time ();
1739
1740   g_test_add_func ("/gtask/basic", test_basic);
1741   g_test_add_func ("/gtask/error", test_error);
1742   g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
1743   g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
1744   g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
1745   g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
1746   g_test_add_func ("/gtask/no-callback", test_no_callback);
1747   g_test_add_func ("/gtask/report-error", test_report_error);
1748   g_test_add_func ("/gtask/priority", test_priority);
1749   g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
1750   g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
1751   g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
1752   g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
1753   g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
1754   g_test_add_func ("/gtask/run-in-thread-nested", test_run_in_thread_nested);
1755   g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
1756   g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
1757   g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
1758   g_test_add_func ("/gtask/return-pointer", test_return_pointer);
1759   g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
1760   g_test_add_func ("/gtask/legacy-error", test_legacy_error);
1761
1762   ret = g_test_run();
1763
1764   g_main_loop_unref (loop);
1765
1766   return ret;
1767 }