Add some more cases to the app-id unit tests
[glib.git] / gio / tests / task.c
blob60ca2847a4d97d2097ba01180ce42375c9207d08
1 /*
2 * Copyright 2012 Red Hat, Inc.
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.
9 * See the included COPYING file for more information.
12 #include <gio/gio.h>
13 #include <string.h>
15 static GMainLoop *loop;
16 static GThread *main_thread;
17 static gssize magic;
19 /* We need objects for a few tests where we don't care what type
20 * they are, just that they're GObjects.
22 #define g_dummy_object_new g_socket_client_new
24 static gboolean
25 idle_quit_loop (gpointer user_data)
27 g_main_loop_quit (loop);
28 return FALSE;
31 static void
32 completed_cb (GObject *gobject,
33 GParamSpec *pspec,
34 gpointer user_data)
36 gboolean *notification_emitted = user_data;
37 *notification_emitted = TRUE;
40 static void
41 wait_for_completed_notification (GTask *task)
43 gboolean notification_emitted = FALSE;
44 gboolean is_completed = FALSE;
46 /* Hold a ref. so we can check the :completed property afterwards. */
47 g_object_ref (task);
49 g_signal_connect (task, "notify::completed",
50 (GCallback) completed_cb, &notification_emitted);
51 g_idle_add (idle_quit_loop, NULL);
52 g_main_loop_run (loop);
53 g_assert_true (notification_emitted);
55 g_assert_true (g_task_get_completed (task));
56 g_object_get (G_OBJECT (task), "completed", &is_completed, NULL);
57 g_assert_true (is_completed);
59 g_object_unref (task);
62 /* test_basic */
64 static void
65 basic_callback (GObject *object,
66 GAsyncResult *result,
67 gpointer user_data)
69 gssize *result_out = user_data;
70 GError *error = NULL;
72 g_assert (object == NULL);
73 g_assert (g_task_is_valid (result, object));
74 g_assert (g_async_result_get_user_data (result) == user_data);
75 g_assert (!g_task_had_error (G_TASK (result)));
76 g_assert_false (g_task_get_completed (G_TASK (result)));
78 *result_out = g_task_propagate_int (G_TASK (result), &error);
79 g_assert_no_error (error);
81 g_assert (!g_task_had_error (G_TASK (result)));
83 g_main_loop_quit (loop);
86 static gboolean
87 basic_return (gpointer user_data)
89 GTask *task = user_data;
91 g_task_return_int (task, magic);
92 g_object_unref (task);
94 return FALSE;
97 static void
98 basic_destroy_notify (gpointer user_data)
100 gboolean *destroyed = user_data;
102 *destroyed = TRUE;
105 static void
106 test_basic (void)
108 GTask *task;
109 gssize result;
110 gboolean task_data_destroyed = FALSE;
111 gboolean notification_emitted = FALSE;
113 task = g_task_new (NULL, NULL, basic_callback, &result);
114 g_task_set_task_data (task, &task_data_destroyed, basic_destroy_notify);
115 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
116 g_signal_connect (task, "notify::completed",
117 (GCallback) completed_cb, &notification_emitted);
119 g_idle_add (basic_return, task);
120 g_main_loop_run (loop);
122 g_assert_cmpint (result, ==, magic);
123 g_assert (task_data_destroyed == TRUE);
124 g_assert_true (notification_emitted);
125 g_assert (task == NULL);
128 /* test_error */
130 static void
131 error_callback (GObject *object,
132 GAsyncResult *result,
133 gpointer user_data)
135 gssize *result_out = user_data;
136 GError *error = NULL;
138 g_assert (object == NULL);
139 g_assert (g_task_is_valid (result, object));
140 g_assert (g_async_result_get_user_data (result) == user_data);
141 g_assert (g_task_had_error (G_TASK (result)));
142 g_assert_false (g_task_get_completed (G_TASK (result)));
144 *result_out = g_task_propagate_int (G_TASK (result), &error);
145 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
146 g_error_free (error);
148 g_assert (g_task_had_error (G_TASK (result)));
150 g_main_loop_quit (loop);
153 static gboolean
154 error_return (gpointer user_data)
156 GTask *task = user_data;
158 g_task_return_new_error (task,
159 G_IO_ERROR, G_IO_ERROR_FAILED,
160 "Failed");
161 g_object_unref (task);
163 return FALSE;
166 static void
167 error_destroy_notify (gpointer user_data)
169 gboolean *destroyed = user_data;
171 *destroyed = TRUE;
174 static void
175 test_error (void)
177 GTask *task;
178 gssize result;
179 gboolean first_task_data_destroyed = FALSE;
180 gboolean second_task_data_destroyed = FALSE;
181 gboolean notification_emitted = FALSE;
183 task = g_task_new (NULL, NULL, error_callback, &result);
184 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
185 g_signal_connect (task, "notify::completed",
186 (GCallback) completed_cb, &notification_emitted);
188 g_assert (first_task_data_destroyed == FALSE);
189 g_task_set_task_data (task, &first_task_data_destroyed, error_destroy_notify);
190 g_assert (first_task_data_destroyed == FALSE);
192 /* Calling g_task_set_task_data() again will destroy the first data */
193 g_task_set_task_data (task, &second_task_data_destroyed, error_destroy_notify);
194 g_assert (first_task_data_destroyed == TRUE);
195 g_assert (second_task_data_destroyed == FALSE);
197 g_idle_add (error_return, task);
198 g_main_loop_run (loop);
200 g_assert_cmpint (result, ==, -1);
201 g_assert (second_task_data_destroyed == TRUE);
202 g_assert_true (notification_emitted);
203 g_assert (task == NULL);
206 /* test_return_from_same_iteration: calling g_task_return_* from the
207 * loop iteration the task was created in defers completion until the
208 * next iteration.
210 gboolean same_result = FALSE;
211 gboolean same_notification_emitted = FALSE;
213 static void
214 same_callback (GObject *object,
215 GAsyncResult *result,
216 gpointer user_data)
218 gboolean *result_out = user_data;
219 GError *error = NULL;
221 g_assert (object == NULL);
222 g_assert (g_task_is_valid (result, object));
223 g_assert (g_async_result_get_user_data (result) == user_data);
224 g_assert (!g_task_had_error (G_TASK (result)));
225 g_assert_false (g_task_get_completed (G_TASK (result)));
227 *result_out = g_task_propagate_boolean (G_TASK (result), &error);
228 g_assert_no_error (error);
230 g_assert (!g_task_had_error (G_TASK (result)));
232 g_main_loop_quit (loop);
235 static gboolean
236 same_start (gpointer user_data)
238 gpointer *weak_pointer = user_data;
239 GTask *task;
241 task = g_task_new (NULL, NULL, same_callback, &same_result);
242 *weak_pointer = task;
243 g_object_add_weak_pointer (G_OBJECT (task), weak_pointer);
244 g_signal_connect (task, "notify::completed",
245 (GCallback) completed_cb, &same_notification_emitted);
247 g_task_return_boolean (task, TRUE);
248 g_object_unref (task);
250 /* same_callback should not have been invoked yet */
251 g_assert (same_result == FALSE);
252 g_assert (*weak_pointer == task);
253 g_assert_false (same_notification_emitted);
255 return FALSE;
258 static void
259 test_return_from_same_iteration (void)
261 gpointer weak_pointer;
263 g_idle_add (same_start, &weak_pointer);
264 g_main_loop_run (loop);
266 g_assert (same_result == TRUE);
267 g_assert (weak_pointer == NULL);
268 g_assert_true (same_notification_emitted);
271 /* test_return_from_toplevel: calling g_task_return_* from outside any
272 * main loop completes the task inside the main loop.
274 gboolean toplevel_notification_emitted = FALSE;
276 static void
277 toplevel_callback (GObject *object,
278 GAsyncResult *result,
279 gpointer user_data)
281 gboolean *result_out = user_data;
282 GError *error = NULL;
284 g_assert (object == NULL);
285 g_assert (g_task_is_valid (result, object));
286 g_assert (g_async_result_get_user_data (result) == user_data);
287 g_assert (!g_task_had_error (G_TASK (result)));
288 g_assert_false (g_task_get_completed (G_TASK (result)));
290 *result_out = g_task_propagate_boolean (G_TASK (result), &error);
291 g_assert_no_error (error);
293 g_assert (!g_task_had_error (G_TASK (result)));
295 g_main_loop_quit (loop);
298 static void
299 test_return_from_toplevel (void)
301 GTask *task;
302 gboolean result = FALSE;
304 task = g_task_new (NULL, NULL, toplevel_callback, &result);
305 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
306 g_signal_connect (task, "notify::completed",
307 (GCallback) completed_cb, &toplevel_notification_emitted);
309 g_task_return_boolean (task, TRUE);
310 g_object_unref (task);
312 /* toplevel_callback should not have been invoked yet */
313 g_assert (result == FALSE);
314 g_assert (task != NULL);
315 g_assert_false (toplevel_notification_emitted);
317 g_main_loop_run (loop);
319 g_assert (result == TRUE);
320 g_assert (task == NULL);
321 g_assert_true (toplevel_notification_emitted);
324 /* test_return_from_anon_thread: calling g_task_return_* from a
325 * thread with no thread-default main context will complete the
326 * task in the task's context/thread.
329 gboolean anon_thread_notification_emitted = FALSE;
330 GThread *anon_thread;
332 static void
333 anon_callback (GObject *object,
334 GAsyncResult *result,
335 gpointer user_data)
337 gssize *result_out = user_data;
338 GError *error = NULL;
340 g_assert (object == NULL);
341 g_assert (g_task_is_valid (result, object));
342 g_assert (g_async_result_get_user_data (result) == user_data);
343 g_assert (!g_task_had_error (G_TASK (result)));
344 g_assert_false (g_task_get_completed (G_TASK (result)));
346 g_assert (g_thread_self () == main_thread);
348 *result_out = g_task_propagate_int (G_TASK (result), &error);
349 g_assert_no_error (error);
351 g_assert (!g_task_had_error (G_TASK (result)));
353 g_main_loop_quit (loop);
356 static gpointer
357 anon_thread_func (gpointer user_data)
359 GTask *task = user_data;
361 g_task_return_int (task, magic);
362 g_object_unref (task);
364 return NULL;
367 static gboolean
368 anon_start (gpointer user_data)
370 GTask *task = user_data;
372 anon_thread = g_thread_new ("test_return_from_anon_thread",
373 anon_thread_func, task);
374 return FALSE;
377 static void
378 test_return_from_anon_thread (void)
380 GTask *task;
381 gssize result = 0;
383 task = g_task_new (NULL, NULL, anon_callback, &result);
384 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
385 g_signal_connect (task, "notify::completed",
386 (GCallback) completed_cb,
387 &anon_thread_notification_emitted);
389 g_idle_add (anon_start, task);
390 g_main_loop_run (loop);
392 g_thread_join (anon_thread);
394 g_assert_cmpint (result, ==, magic);
395 g_assert (task == NULL);
396 g_assert_true (anon_thread_notification_emitted);
399 /* test_return_from_wrong_thread: calling g_task_return_* from a
400 * thread with its own thread-default main context will complete the
401 * task in the task's context/thread.
404 gboolean wrong_thread_notification_emitted = FALSE;
405 GThread *wrong_thread;
407 static void
408 wrong_callback (GObject *object,
409 GAsyncResult *result,
410 gpointer user_data)
412 gssize *result_out = user_data;
413 GError *error = NULL;
415 g_assert (object == NULL);
416 g_assert (g_task_is_valid (result, object));
417 g_assert (g_async_result_get_user_data (result) == user_data);
418 g_assert (!g_task_had_error (G_TASK (result)));
419 g_assert_false (g_task_get_completed (G_TASK (result)));
421 g_assert (g_thread_self () == main_thread);
423 *result_out = g_task_propagate_int (G_TASK (result), &error);
424 g_assert_no_error (error);
426 g_assert (!g_task_had_error (G_TASK (result)));
428 g_main_loop_quit (loop);
431 static gpointer
432 wrong_thread_func (gpointer user_data)
434 GTask *task = user_data;
435 GMainContext *context;
437 context = g_main_context_new ();
438 g_main_context_push_thread_default (context);
440 g_assert (g_task_get_context (task) != context);
442 g_task_return_int (task, magic);
443 g_object_unref (task);
445 g_main_context_pop_thread_default (context);
446 g_main_context_unref (context);
448 return NULL;
451 static gboolean
452 wrong_start (gpointer user_data)
454 GTask *task = user_data;
456 wrong_thread = g_thread_new ("test_return_from_anon_thread",
457 wrong_thread_func, task);
458 return FALSE;
461 static void
462 test_return_from_wrong_thread (void)
464 GTask *task;
465 gssize result = 0;
467 task = g_task_new (NULL, NULL, wrong_callback, &result);
468 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
469 g_signal_connect (task, "notify::completed",
470 (GCallback) completed_cb,
471 &wrong_thread_notification_emitted);
473 g_idle_add (wrong_start, task);
474 g_main_loop_run (loop);
476 g_thread_join (wrong_thread);
478 g_assert_cmpint (result, ==, magic);
479 g_assert (task == NULL);
480 g_assert_true (wrong_thread_notification_emitted);
483 /* test_no_callback */
485 static void
486 test_no_callback (void)
488 GTask *task;
490 task = g_task_new (NULL, NULL, NULL, NULL);
491 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
493 g_task_return_boolean (task, TRUE);
494 g_object_unref (task);
496 /* Even though there’s no callback, the :completed notification has to
497 * happen in an idle handler. */
498 g_assert_nonnull (task);
499 wait_for_completed_notification (task);
500 g_assert_null (task);
503 /* test_report_error */
505 static void test_report_error (void);
506 gboolean error_notification_emitted = FALSE;
508 static void
509 report_callback (GObject *object,
510 GAsyncResult *result,
511 gpointer user_data)
513 gpointer *weak_pointer = user_data;
514 GError *error = NULL;
515 gssize ret;
517 g_assert (object == NULL);
518 g_assert (g_task_is_valid (result, object));
519 g_assert (g_async_result_get_user_data (result) == user_data);
520 g_assert (g_async_result_is_tagged (result, test_report_error));
521 g_assert (g_task_get_source_tag (G_TASK (result)) == test_report_error);
522 g_assert (g_task_had_error (G_TASK (result)));
523 g_assert_false (g_task_get_completed (G_TASK (result)));
525 ret = g_task_propagate_int (G_TASK (result), &error);
526 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
527 g_assert_cmpint (ret, ==, -1);
528 g_error_free (error);
530 g_assert (g_task_had_error (G_TASK (result)));
532 *weak_pointer = result;
533 g_object_add_weak_pointer (G_OBJECT (result), weak_pointer);
534 g_signal_connect (result, "notify::completed",
535 (GCallback) completed_cb, &error_notification_emitted);
537 g_main_loop_quit (loop);
540 static void
541 test_report_error (void)
543 gpointer weak_pointer = (gpointer)-1;
545 g_task_report_new_error (NULL, report_callback, &weak_pointer,
546 test_report_error,
547 G_IO_ERROR, G_IO_ERROR_FAILED,
548 "Failed");
549 g_main_loop_run (loop);
551 g_assert (weak_pointer == NULL);
552 g_assert_true (error_notification_emitted);
555 /* test_priority: tasks complete in priority order */
557 static int counter = 0;
559 static void
560 priority_callback (GObject *object,
561 GAsyncResult *result,
562 gpointer user_data)
564 gssize *ret_out = user_data;
565 GError *error = NULL;
567 g_assert (object == NULL);
568 g_assert (g_task_is_valid (result, object));
569 g_assert (g_async_result_get_user_data (result) == user_data);
570 g_assert (!g_task_had_error (G_TASK (result)));
571 g_assert_false (g_task_get_completed (G_TASK (result)));
573 g_task_propagate_boolean (G_TASK (result), &error);
574 g_assert_no_error (error);
576 g_assert (!g_task_had_error (G_TASK (result)));
578 *ret_out = ++counter;
580 if (counter == 3)
581 g_main_loop_quit (loop);
584 static void
585 test_priority (void)
587 GTask *t1, *t2, *t3;
588 gssize ret1, ret2, ret3;
590 /* t2 has higher priority than either t1 or t3, so we can't
591 * accidentally pass the test just by completing the tasks in the
592 * order they were created (or in reverse order).
595 t1 = g_task_new (NULL, NULL, priority_callback, &ret1);
596 g_task_set_priority (t1, G_PRIORITY_DEFAULT);
597 g_task_return_boolean (t1, TRUE);
598 g_object_unref (t1);
600 t2 = g_task_new (NULL, NULL, priority_callback, &ret2);
601 g_task_set_priority (t2, G_PRIORITY_HIGH);
602 g_task_return_boolean (t2, TRUE);
603 g_object_unref (t2);
605 t3 = g_task_new (NULL, NULL, priority_callback, &ret3);
606 g_task_set_priority (t3, G_PRIORITY_LOW);
607 g_task_return_boolean (t3, TRUE);
608 g_object_unref (t3);
610 g_main_loop_run (loop);
612 g_assert_cmpint (ret2, ==, 1);
613 g_assert_cmpint (ret1, ==, 2);
614 g_assert_cmpint (ret3, ==, 3);
617 /* test_check_cancellable: cancellation overrides return value */
619 enum {
620 CANCEL_BEFORE = (1 << 1),
621 CANCEL_AFTER = (1 << 2),
622 CHECK_CANCELLABLE = (1 << 3)
624 #define NUM_CANCEL_TESTS (CANCEL_BEFORE | CANCEL_AFTER | CHECK_CANCELLABLE)
626 static void
627 cancel_callback (GObject *object,
628 GAsyncResult *result,
629 gpointer user_data)
631 int state = GPOINTER_TO_INT (user_data);
632 GTask *task;
633 GCancellable *cancellable;
634 GError *error = NULL;
636 g_assert (object == NULL);
637 g_assert (g_task_is_valid (result, object));
638 g_assert (g_async_result_get_user_data (result) == user_data);
640 task = G_TASK (result);
641 cancellable = g_task_get_cancellable (task);
642 g_assert (G_IS_CANCELLABLE (cancellable));
644 if (state & (CANCEL_BEFORE | CANCEL_AFTER))
645 g_assert (g_cancellable_is_cancelled (cancellable));
646 else
647 g_assert (!g_cancellable_is_cancelled (cancellable));
649 if (state & CHECK_CANCELLABLE)
650 g_assert (g_task_get_check_cancellable (task));
651 else
652 g_assert (!g_task_get_check_cancellable (task));
654 if (g_task_propagate_boolean (task, &error))
656 g_assert (!g_cancellable_is_cancelled (cancellable) ||
657 !g_task_get_check_cancellable (task));
659 else
661 g_assert (g_cancellable_is_cancelled (cancellable) &&
662 g_task_get_check_cancellable (task));
663 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
664 g_error_free (error);
667 g_main_loop_quit (loop);
670 static void
671 test_check_cancellable (void)
673 GTask *task;
674 GCancellable *cancellable;
675 int state;
677 cancellable = g_cancellable_new ();
679 for (state = 0; state <= NUM_CANCEL_TESTS; state++)
681 task = g_task_new (NULL, cancellable, cancel_callback,
682 GINT_TO_POINTER (state));
683 g_task_set_check_cancellable (task, (state & CHECK_CANCELLABLE) != 0);
685 if (state & CANCEL_BEFORE)
686 g_cancellable_cancel (cancellable);
687 g_task_return_boolean (task, TRUE);
688 if (state & CANCEL_AFTER)
689 g_cancellable_cancel (cancellable);
691 g_main_loop_run (loop);
692 g_object_unref (task);
693 g_cancellable_reset (cancellable);
696 g_object_unref (cancellable);
699 /* test_return_if_cancelled */
701 static void
702 return_if_cancelled_callback (GObject *object,
703 GAsyncResult *result,
704 gpointer user_data)
706 GError *error = NULL;
708 g_assert (object == NULL);
709 g_assert (g_task_is_valid (result, object));
710 g_assert (g_async_result_get_user_data (result) == user_data);
711 g_assert (g_task_had_error (G_TASK (result)));
712 g_assert_false (g_task_get_completed (G_TASK (result)));
714 g_task_propagate_boolean (G_TASK (result), &error);
715 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
716 g_clear_error (&error);
718 g_assert (g_task_had_error (G_TASK (result)));
720 g_main_loop_quit (loop);
723 static void
724 test_return_if_cancelled (void)
726 GTask *task;
727 GCancellable *cancellable;
728 gboolean cancelled;
729 gboolean notification_emitted = FALSE;
731 cancellable = g_cancellable_new ();
733 task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
734 g_signal_connect (task, "notify::completed",
735 (GCallback) completed_cb, &notification_emitted);
737 g_cancellable_cancel (cancellable);
738 cancelled = g_task_return_error_if_cancelled (task);
739 g_assert (cancelled);
740 g_assert_false (notification_emitted);
741 g_main_loop_run (loop);
742 g_object_unref (task);
743 g_assert_true (notification_emitted);
744 g_cancellable_reset (cancellable);
746 notification_emitted = FALSE;
748 task = g_task_new (NULL, cancellable, return_if_cancelled_callback, NULL);
749 g_signal_connect (task, "notify::completed",
750 (GCallback) completed_cb, &notification_emitted);
752 g_task_set_check_cancellable (task, FALSE);
753 g_cancellable_cancel (cancellable);
754 cancelled = g_task_return_error_if_cancelled (task);
755 g_assert (cancelled);
756 g_assert_false (notification_emitted);
757 g_main_loop_run (loop);
758 g_object_unref (task);
759 g_assert_true (notification_emitted);
760 g_object_unref (cancellable);
763 /* test_run_in_thread */
765 static GMutex run_in_thread_mutex;
766 static GCond run_in_thread_cond;
768 static void
769 task_weak_notify (gpointer user_data,
770 GObject *ex_task)
772 gboolean *weak_notify_ran = user_data;
774 g_mutex_lock (&run_in_thread_mutex);
775 *weak_notify_ran = TRUE;
776 g_cond_signal (&run_in_thread_cond);
777 g_mutex_unlock (&run_in_thread_mutex);
780 static void
781 run_in_thread_callback (GObject *object,
782 GAsyncResult *result,
783 gpointer user_data)
785 gboolean *done = user_data;
786 GError *error = NULL;
787 gssize ret;
789 g_assert (g_thread_self () == main_thread);
791 g_assert (object == NULL);
792 g_assert (g_task_is_valid (result, object));
793 g_assert (g_async_result_get_user_data (result) == user_data);
794 g_assert (!g_task_had_error (G_TASK (result)));
795 g_assert_false (g_task_get_completed (G_TASK (result)));
797 ret = g_task_propagate_int (G_TASK (result), &error);
798 g_assert_no_error (error);
799 g_assert_cmpint (ret, ==, magic);
801 g_assert (!g_task_had_error (G_TASK (result)));
803 *done = TRUE;
804 g_main_loop_quit (loop);
807 static void
808 run_in_thread_thread (GTask *task,
809 gpointer source_object,
810 gpointer task_data,
811 GCancellable *cancellable)
813 gboolean *thread_ran = task_data;
815 g_assert (source_object == g_task_get_source_object (task));
816 g_assert (task_data == g_task_get_task_data (task));
817 g_assert (cancellable == g_task_get_cancellable (task));
818 g_assert_false (g_task_get_completed (task));
820 g_assert (g_thread_self () != main_thread);
822 g_mutex_lock (&run_in_thread_mutex);
823 *thread_ran = TRUE;
824 g_cond_signal (&run_in_thread_cond);
825 g_mutex_unlock (&run_in_thread_mutex);
827 g_task_return_int (task, magic);
830 static void
831 test_run_in_thread (void)
833 GTask *task;
834 volatile gboolean thread_ran = FALSE;
835 volatile gboolean weak_notify_ran = FALSE;
836 gboolean notification_emitted = FALSE;
837 gboolean done = FALSE;
839 task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
840 g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
841 g_signal_connect (task, "notify::completed",
842 (GCallback) completed_cb, &notification_emitted);
844 g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
845 g_task_run_in_thread (task, run_in_thread_thread);
846 g_object_unref (task);
848 g_mutex_lock (&run_in_thread_mutex);
849 while (!thread_ran)
850 g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
851 g_mutex_unlock (&run_in_thread_mutex);
853 g_assert (done == FALSE);
854 g_assert (weak_notify_ran == FALSE);
856 g_main_loop_run (loop);
858 g_assert (done == TRUE);
859 g_assert_true (notification_emitted);
861 g_mutex_lock (&run_in_thread_mutex);
862 while (!weak_notify_ran)
863 g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
864 g_mutex_unlock (&run_in_thread_mutex);
867 /* test_run_in_thread_sync */
869 static void
870 run_in_thread_sync_callback (GObject *object,
871 GAsyncResult *result,
872 gpointer user_data)
874 /* g_task_run_in_thread_sync() does not invoke the task's callback */
875 g_assert_not_reached ();
878 static void
879 run_in_thread_sync_thread (GTask *task,
880 gpointer source_object,
881 gpointer task_data,
882 GCancellable *cancellable)
884 gboolean *thread_ran = task_data;
886 g_assert (source_object == g_task_get_source_object (task));
887 g_assert (task_data == g_task_get_task_data (task));
888 g_assert (cancellable == g_task_get_cancellable (task));
889 g_assert_false (g_task_get_completed (task));
891 g_assert (g_thread_self () != main_thread);
893 *thread_ran = TRUE;
894 g_task_return_int (task, magic);
897 static void
898 test_run_in_thread_sync (void)
900 GTask *task;
901 gboolean thread_ran = FALSE;
902 gssize ret;
903 gboolean notification_emitted = FALSE;
904 GError *error = NULL;
906 task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
907 g_signal_connect (task, "notify::completed",
908 (GCallback) completed_cb,
909 &notification_emitted);
911 g_task_set_task_data (task, &thread_ran, NULL);
912 g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
914 g_assert (thread_ran == TRUE);
915 g_assert (task != NULL);
916 g_assert (!g_task_had_error (task));
917 g_assert_true (g_task_get_completed (task));
918 g_assert_true (notification_emitted);
920 ret = g_task_propagate_int (task, &error);
921 g_assert_no_error (error);
922 g_assert_cmpint (ret, ==, magic);
924 g_assert (!g_task_had_error (task));
926 g_object_unref (task);
929 /* test_run_in_thread_priority */
931 static GMutex fake_task_mutex, last_fake_task_mutex;
932 static gint sequence_number = 0;
934 static void
935 quit_main_loop_callback (GObject *object,
936 GAsyncResult *result,
937 gpointer user_data)
939 GError *error = NULL;
940 gboolean ret;
942 g_assert (g_thread_self () == main_thread);
944 g_assert (object == NULL);
945 g_assert (g_task_is_valid (result, object));
946 g_assert (g_async_result_get_user_data (result) == user_data);
947 g_assert (!g_task_had_error (G_TASK (result)));
948 g_assert_false (g_task_get_completed (G_TASK (result)));
950 ret = g_task_propagate_boolean (G_TASK (result), &error);
951 g_assert_no_error (error);
952 g_assert_cmpint (ret, ==, TRUE);
954 g_assert (!g_task_had_error (G_TASK (result)));
956 g_main_loop_quit (loop);
959 static void
960 set_sequence_number_thread (GTask *task,
961 gpointer source_object,
962 gpointer task_data,
963 GCancellable *cancellable)
965 gint *seq_no_p = task_data;
967 *seq_no_p = ++sequence_number;
968 g_task_return_boolean (task, TRUE);
971 static void
972 fake_task_thread (GTask *task,
973 gpointer source_object,
974 gpointer task_data,
975 GCancellable *cancellable)
977 GMutex *mutex = task_data;
979 g_mutex_lock (mutex);
980 g_mutex_unlock (mutex);
981 g_task_return_boolean (task, TRUE);
984 #define G_TASK_THREAD_POOL_SIZE 10
985 static int fake_tasks_running;
987 static void
988 fake_task_callback (GObject *source,
989 GAsyncResult *result,
990 gpointer user_data)
992 if (--fake_tasks_running == 0)
993 g_main_loop_quit (loop);
996 static void
997 clog_up_thread_pool (void)
999 GTask *task;
1000 int i;
1002 g_thread_pool_stop_unused_threads ();
1004 g_mutex_lock (&fake_task_mutex);
1005 for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
1007 task = g_task_new (NULL, NULL, fake_task_callback, NULL);
1008 g_task_set_task_data (task, &fake_task_mutex, NULL);
1009 g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
1010 g_task_set_priority (task, G_PRIORITY_HIGH * 2);
1011 g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
1012 g_task_run_in_thread (task, fake_task_thread);
1013 g_object_unref (task);
1014 fake_tasks_running++;
1017 g_mutex_lock (&last_fake_task_mutex);
1018 task = g_task_new (NULL, NULL, NULL, NULL);
1019 g_task_set_task_data (task, &last_fake_task_mutex, NULL);
1020 g_task_set_priority (task, G_PRIORITY_HIGH * 2);
1021 g_task_run_in_thread (task, fake_task_thread);
1022 g_object_unref (task);
1025 static void
1026 unclog_thread_pool (void)
1028 g_mutex_unlock (&fake_task_mutex);
1029 g_main_loop_run (loop);
1032 static void
1033 test_run_in_thread_priority (void)
1035 GTask *task;
1036 GCancellable *cancellable;
1037 int seq_a, seq_b, seq_c, seq_d;
1039 clog_up_thread_pool ();
1041 /* Queue three more tasks that we'll arrange to have run serially */
1042 task = g_task_new (NULL, NULL, NULL, NULL);
1043 g_task_set_task_data (task, &seq_a, NULL);
1044 g_task_run_in_thread (task, set_sequence_number_thread);
1045 g_object_unref (task);
1047 task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
1048 g_task_set_task_data (task, &seq_b, NULL);
1049 g_task_set_priority (task, G_PRIORITY_LOW);
1050 g_task_run_in_thread (task, set_sequence_number_thread);
1051 g_object_unref (task);
1053 task = g_task_new (NULL, NULL, NULL, NULL);
1054 g_task_set_task_data (task, &seq_c, NULL);
1055 g_task_set_priority (task, G_PRIORITY_HIGH);
1056 g_task_run_in_thread (task, set_sequence_number_thread);
1057 g_object_unref (task);
1059 cancellable = g_cancellable_new ();
1060 task = g_task_new (NULL, cancellable, NULL, NULL);
1061 g_task_set_task_data (task, &seq_d, NULL);
1062 g_task_run_in_thread (task, set_sequence_number_thread);
1063 g_cancellable_cancel (cancellable);
1064 g_object_unref (cancellable);
1065 g_object_unref (task);
1067 /* Let the last fake task complete; the four other tasks will then
1068 * complete serially, in the order D, C, A, B, and B will quit the
1069 * main loop.
1071 g_mutex_unlock (&last_fake_task_mutex);
1072 g_main_loop_run (loop);
1074 g_assert_cmpint (seq_d, ==, 1);
1075 g_assert_cmpint (seq_c, ==, 2);
1076 g_assert_cmpint (seq_a, ==, 3);
1077 g_assert_cmpint (seq_b, ==, 4);
1079 unclog_thread_pool ();
1082 /* test_run_in_thread_nested: task threads that block waiting on
1083 * other task threads will not cause the thread pool to starve.
1086 static void
1087 run_nested_task_thread (GTask *task,
1088 gpointer source_object,
1089 gpointer task_data,
1090 GCancellable *cancellable)
1092 GTask *nested;
1093 int *nested_tasks_left = task_data;
1095 if ((*nested_tasks_left)--)
1097 nested = g_task_new (NULL, NULL, NULL, NULL);
1098 g_task_set_task_data (nested, nested_tasks_left, NULL);
1099 g_task_run_in_thread_sync (nested, run_nested_task_thread);
1100 g_object_unref (nested);
1103 g_task_return_boolean (task, TRUE);
1106 static void
1107 test_run_in_thread_nested (void)
1109 GTask *task;
1110 int nested_tasks_left = 2;
1112 clog_up_thread_pool ();
1114 task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
1115 g_task_set_task_data (task, &nested_tasks_left, NULL);
1116 g_task_run_in_thread (task, run_nested_task_thread);
1117 g_object_unref (task);
1119 g_mutex_unlock (&last_fake_task_mutex);
1120 g_main_loop_run (loop);
1122 unclog_thread_pool ();
1125 /* test_run_in_thread_overflow: if you queue lots and lots and lots of
1126 * tasks, they won't all run at once.
1128 static GMutex overflow_mutex;
1130 static void
1131 run_overflow_task_thread (GTask *task,
1132 gpointer source_object,
1133 gpointer task_data,
1134 GCancellable *cancellable)
1136 gchar *result = task_data;
1138 if (g_task_return_error_if_cancelled (task))
1140 *result = 'X';
1141 return;
1144 /* Block until the main thread is ready. */
1145 g_mutex_lock (&overflow_mutex);
1146 g_mutex_unlock (&overflow_mutex);
1148 *result = '.';
1150 g_task_return_boolean (task, TRUE);
1153 #define NUM_OVERFLOW_TASKS 1024
1155 static void
1156 test_run_in_thread_overflow (void)
1158 GCancellable *cancellable;
1159 GTask *task;
1160 gchar buf[NUM_OVERFLOW_TASKS + 1];
1161 gint i;
1163 /* Queue way too many tasks and then sleep for a bit. The first 10
1164 * tasks will be dispatched to threads and will then block on
1165 * overflow_mutex, so more threads will be created while this thread
1166 * is sleeping. Then we cancel the cancellable, unlock the mutex,
1167 * wait for all of the tasks to complete, and make sure that we got
1168 * the behavior we expected.
1171 memset (buf, 0, sizeof (buf));
1172 cancellable = g_cancellable_new ();
1174 g_mutex_lock (&overflow_mutex);
1176 for (i = 0; i < NUM_OVERFLOW_TASKS; i++)
1178 task = g_task_new (NULL, cancellable, NULL, NULL);
1179 g_task_set_task_data (task, buf + i, NULL);
1180 g_task_run_in_thread (task, run_overflow_task_thread);
1181 g_object_unref (task);
1184 if (g_test_slow ())
1185 g_usleep (5000000); /* 5 s */
1186 else
1187 g_usleep (500000); /* 0.5 s */
1188 g_cancellable_cancel (cancellable);
1189 g_object_unref (cancellable);
1191 g_mutex_unlock (&overflow_mutex);
1193 /* Wait for all tasks to complete. */
1194 while (strlen (buf) != NUM_OVERFLOW_TASKS)
1195 g_usleep (1000);
1197 i = strspn (buf, ".");
1198 /* Given the sleep times above, i should be 14 for normal, 40 for
1199 * slow. But if the machine is too slow/busy then the scheduling
1200 * might get messed up and we'll get more or fewer threads than
1201 * expected. But there are limits to how messed up it could
1202 * plausibly get (and we hope that if gtask is actually broken then
1203 * it will exceed those limits).
1205 g_assert_cmpint (i, >=, 10);
1206 if (g_test_slow ())
1207 g_assert_cmpint (i, <, 50);
1208 else
1209 g_assert_cmpint (i, <, 20);
1211 g_assert_cmpint (i + strspn (buf + i, "X"), ==, NUM_OVERFLOW_TASKS);
1214 /* test_return_on_cancel */
1216 GMutex roc_init_mutex, roc_finish_mutex;
1217 GCond roc_init_cond, roc_finish_cond;
1219 typedef enum {
1220 THREAD_STARTING,
1221 THREAD_RUNNING,
1222 THREAD_CANCELLED,
1223 THREAD_COMPLETED
1224 } ThreadState;
1226 static void
1227 return_on_cancel_callback (GObject *object,
1228 GAsyncResult *result,
1229 gpointer user_data)
1231 gboolean *callback_ran = user_data;
1232 GError *error = NULL;
1233 gssize ret;
1235 g_assert (g_thread_self () == main_thread);
1237 g_assert (object == NULL);
1238 g_assert (g_task_is_valid (result, object));
1239 g_assert (g_async_result_get_user_data (result) == user_data);
1240 g_assert (g_task_had_error (G_TASK (result)));
1241 g_assert_false (g_task_get_completed (G_TASK (result)));
1243 ret = g_task_propagate_int (G_TASK (result), &error);
1244 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1245 g_clear_error (&error);
1246 g_assert_cmpint (ret, ==, -1);
1248 g_assert (g_task_had_error (G_TASK (result)));
1250 *callback_ran = TRUE;
1251 g_main_loop_quit (loop);
1254 static void
1255 return_on_cancel_thread (GTask *task,
1256 gpointer source_object,
1257 gpointer task_data,
1258 GCancellable *cancellable)
1260 ThreadState *state = task_data;
1262 g_assert (source_object == g_task_get_source_object (task));
1263 g_assert (task_data == g_task_get_task_data (task));
1264 g_assert (cancellable == g_task_get_cancellable (task));
1266 g_assert (g_thread_self () != main_thread);
1268 g_mutex_lock (&roc_init_mutex);
1269 *state = THREAD_RUNNING;
1270 g_cond_signal (&roc_init_cond);
1271 g_mutex_unlock (&roc_init_mutex);
1273 g_mutex_lock (&roc_finish_mutex);
1275 if (!g_task_get_return_on_cancel (task) ||
1276 g_task_set_return_on_cancel (task, FALSE))
1278 *state = THREAD_COMPLETED;
1279 g_task_return_int (task, magic);
1281 else
1282 *state = THREAD_CANCELLED;
1284 g_cond_signal (&roc_finish_cond);
1285 g_mutex_unlock (&roc_finish_mutex);
1288 static void
1289 test_return_on_cancel (void)
1291 GTask *task;
1292 GCancellable *cancellable;
1293 volatile ThreadState thread_state;
1294 volatile gboolean weak_notify_ran = FALSE;
1295 gboolean callback_ran;
1296 gboolean notification_emitted = FALSE;
1298 cancellable = g_cancellable_new ();
1300 /* If return-on-cancel is FALSE (default), the task does not return
1301 * early.
1303 callback_ran = FALSE;
1304 thread_state = THREAD_STARTING;
1305 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1306 g_signal_connect (task, "notify::completed",
1307 (GCallback) completed_cb, &notification_emitted);
1309 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1310 g_mutex_lock (&roc_init_mutex);
1311 g_mutex_lock (&roc_finish_mutex);
1312 g_task_run_in_thread (task, return_on_cancel_thread);
1313 g_object_unref (task);
1315 while (thread_state == THREAD_STARTING)
1316 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1317 g_mutex_unlock (&roc_init_mutex);
1319 g_assert (thread_state == THREAD_RUNNING);
1320 g_assert (callback_ran == FALSE);
1322 g_cancellable_cancel (cancellable);
1323 g_mutex_unlock (&roc_finish_mutex);
1324 g_main_loop_run (loop);
1326 g_assert (thread_state == THREAD_COMPLETED);
1327 g_assert (callback_ran == TRUE);
1328 g_assert_true (notification_emitted);
1330 g_cancellable_reset (cancellable);
1332 /* If return-on-cancel is TRUE, it does return early */
1333 callback_ran = FALSE;
1334 notification_emitted = FALSE;
1335 thread_state = THREAD_STARTING;
1336 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1337 g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
1338 g_signal_connect (task, "notify::completed",
1339 (GCallback) completed_cb, &notification_emitted);
1340 g_task_set_return_on_cancel (task, TRUE);
1342 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1343 g_mutex_lock (&roc_init_mutex);
1344 g_mutex_lock (&roc_finish_mutex);
1345 g_task_run_in_thread (task, return_on_cancel_thread);
1346 g_object_unref (task);
1348 while (thread_state == THREAD_STARTING)
1349 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1350 g_mutex_unlock (&roc_init_mutex);
1352 g_assert (thread_state == THREAD_RUNNING);
1353 g_assert (callback_ran == FALSE);
1355 g_cancellable_cancel (cancellable);
1356 g_main_loop_run (loop);
1357 g_assert (thread_state == THREAD_RUNNING);
1358 g_assert (callback_ran == TRUE);
1360 g_assert (weak_notify_ran == FALSE);
1362 while (thread_state == THREAD_RUNNING)
1363 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1364 g_mutex_unlock (&roc_finish_mutex);
1366 g_assert (thread_state == THREAD_CANCELLED);
1367 g_mutex_lock (&run_in_thread_mutex);
1368 while (!weak_notify_ran)
1369 g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
1370 g_mutex_unlock (&run_in_thread_mutex);
1372 g_assert_true (notification_emitted);
1373 g_cancellable_reset (cancellable);
1375 /* If the task is already cancelled before it starts, it returns
1376 * immediately, but the thread func still runs.
1378 callback_ran = FALSE;
1379 notification_emitted = FALSE;
1380 thread_state = THREAD_STARTING;
1381 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1382 g_signal_connect (task, "notify::completed",
1383 (GCallback) completed_cb, &notification_emitted);
1384 g_task_set_return_on_cancel (task, TRUE);
1386 g_cancellable_cancel (cancellable);
1388 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1389 g_mutex_lock (&roc_init_mutex);
1390 g_mutex_lock (&roc_finish_mutex);
1391 g_task_run_in_thread (task, return_on_cancel_thread);
1392 g_object_unref (task);
1394 g_main_loop_run (loop);
1395 g_assert (callback_ran == TRUE);
1397 while (thread_state == THREAD_STARTING)
1398 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1399 g_mutex_unlock (&roc_init_mutex);
1401 g_assert (thread_state == THREAD_RUNNING);
1403 while (thread_state == THREAD_RUNNING)
1404 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1405 g_mutex_unlock (&roc_finish_mutex);
1407 g_assert (thread_state == THREAD_CANCELLED);
1408 g_assert_true (notification_emitted);
1410 g_object_unref (cancellable);
1413 /* test_return_on_cancel_sync */
1415 static gpointer
1416 cancel_sync_runner_thread (gpointer task)
1418 g_task_run_in_thread_sync (task, return_on_cancel_thread);
1419 return NULL;
1422 static void
1423 test_return_on_cancel_sync (void)
1425 GTask *task;
1426 GCancellable *cancellable;
1427 volatile ThreadState thread_state;
1428 GThread *runner_thread;
1429 gssize ret;
1430 GError *error = NULL;
1432 cancellable = g_cancellable_new ();
1434 /* If return-on-cancel is FALSE, the task does not return early.
1436 thread_state = THREAD_STARTING;
1437 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1439 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1440 g_mutex_lock (&roc_init_mutex);
1441 g_mutex_lock (&roc_finish_mutex);
1442 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1443 cancel_sync_runner_thread, task);
1445 while (thread_state == THREAD_STARTING)
1446 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1447 g_mutex_unlock (&roc_init_mutex);
1449 g_assert (thread_state == THREAD_RUNNING);
1451 g_cancellable_cancel (cancellable);
1452 g_mutex_unlock (&roc_finish_mutex);
1453 g_thread_join (runner_thread);
1454 g_assert (thread_state == THREAD_COMPLETED);
1456 ret = g_task_propagate_int (task, &error);
1457 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1458 g_clear_error (&error);
1459 g_assert_cmpint (ret, ==, -1);
1461 g_object_unref (task);
1463 g_cancellable_reset (cancellable);
1465 /* If return-on-cancel is TRUE, it does return early */
1466 thread_state = THREAD_STARTING;
1467 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1468 g_task_set_return_on_cancel (task, TRUE);
1470 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1471 g_mutex_lock (&roc_init_mutex);
1472 g_mutex_lock (&roc_finish_mutex);
1473 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1474 cancel_sync_runner_thread, task);
1476 while (thread_state == THREAD_STARTING)
1477 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1478 g_mutex_unlock (&roc_init_mutex);
1480 g_assert (thread_state == THREAD_RUNNING);
1482 g_cancellable_cancel (cancellable);
1483 g_thread_join (runner_thread);
1484 g_assert (thread_state == THREAD_RUNNING);
1486 ret = g_task_propagate_int (task, &error);
1487 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1488 g_clear_error (&error);
1489 g_assert_cmpint (ret, ==, -1);
1491 g_object_unref (task);
1493 while (thread_state == THREAD_RUNNING)
1494 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1495 g_mutex_unlock (&roc_finish_mutex);
1497 g_assert (thread_state == THREAD_CANCELLED);
1499 g_cancellable_reset (cancellable);
1501 /* If the task is already cancelled before it starts, it returns
1502 * immediately, but the thread func still runs.
1504 thread_state = THREAD_STARTING;
1505 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1506 g_task_set_return_on_cancel (task, TRUE);
1508 g_cancellable_cancel (cancellable);
1510 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1511 g_mutex_lock (&roc_init_mutex);
1512 g_mutex_lock (&roc_finish_mutex);
1513 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1514 cancel_sync_runner_thread, task);
1516 g_thread_join (runner_thread);
1517 g_assert (thread_state == THREAD_STARTING);
1519 ret = g_task_propagate_int (task, &error);
1520 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1521 g_clear_error (&error);
1522 g_assert_cmpint (ret, ==, -1);
1524 g_object_unref (task);
1526 while (thread_state == THREAD_STARTING)
1527 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1528 g_mutex_unlock (&roc_init_mutex);
1530 g_assert (thread_state == THREAD_RUNNING);
1532 while (thread_state == THREAD_RUNNING)
1533 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1534 g_mutex_unlock (&roc_finish_mutex);
1536 g_assert (thread_state == THREAD_CANCELLED);
1538 g_object_unref (cancellable);
1541 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1542 * non-racy
1545 GMutex roca_mutex_1, roca_mutex_2;
1546 GCond roca_cond_1, roca_cond_2;
1548 static void
1549 return_on_cancel_atomic_callback (GObject *object,
1550 GAsyncResult *result,
1551 gpointer user_data)
1553 gboolean *callback_ran = user_data;
1554 GError *error = NULL;
1555 gssize ret;
1557 g_assert (g_thread_self () == main_thread);
1559 g_assert (object == NULL);
1560 g_assert (g_task_is_valid (result, object));
1561 g_assert (g_async_result_get_user_data (result) == user_data);
1562 g_assert (g_task_had_error (G_TASK (result)));
1563 g_assert_false (g_task_get_completed (G_TASK (result)));
1565 ret = g_task_propagate_int (G_TASK (result), &error);
1566 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1567 g_clear_error (&error);
1568 g_assert_cmpint (ret, ==, -1);
1570 g_assert (g_task_had_error (G_TASK (result)));
1572 *callback_ran = TRUE;
1573 g_main_loop_quit (loop);
1576 static void
1577 return_on_cancel_atomic_thread (GTask *task,
1578 gpointer source_object,
1579 gpointer task_data,
1580 GCancellable *cancellable)
1582 gint *state = task_data;
1584 g_assert (source_object == g_task_get_source_object (task));
1585 g_assert (task_data == g_task_get_task_data (task));
1586 g_assert (cancellable == g_task_get_cancellable (task));
1587 g_assert_false (g_task_get_completed (task));
1589 g_assert (g_thread_self () != main_thread);
1590 g_assert_cmpint (*state, ==, 0);
1592 g_mutex_lock (&roca_mutex_1);
1593 *state = 1;
1594 g_cond_signal (&roca_cond_1);
1595 g_mutex_unlock (&roca_mutex_1);
1597 g_mutex_lock (&roca_mutex_2);
1598 if (g_task_set_return_on_cancel (task, FALSE))
1599 *state = 2;
1600 else
1601 *state = 3;
1602 g_cond_signal (&roca_cond_2);
1603 g_mutex_unlock (&roca_mutex_2);
1605 g_mutex_lock (&roca_mutex_1);
1606 if (g_task_set_return_on_cancel (task, TRUE))
1607 *state = 4;
1608 else
1609 *state = 5;
1610 g_cond_signal (&roca_cond_1);
1611 g_mutex_unlock (&roca_mutex_1);
1613 g_mutex_lock (&roca_mutex_2);
1614 if (g_task_set_return_on_cancel (task, TRUE))
1615 *state = 6;
1616 else
1617 *state = 7;
1618 g_cond_signal (&roca_cond_2);
1619 g_mutex_unlock (&roca_mutex_2);
1621 g_task_return_int (task, magic);
1624 static void
1625 test_return_on_cancel_atomic (void)
1627 GTask *task;
1628 GCancellable *cancellable;
1629 volatile gint state;
1630 gboolean notification_emitted = FALSE;
1631 gboolean callback_ran;
1633 cancellable = g_cancellable_new ();
1634 g_mutex_lock (&roca_mutex_1);
1635 g_mutex_lock (&roca_mutex_2);
1637 /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1638 state = 0;
1639 callback_ran = FALSE;
1640 task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1641 g_task_set_return_on_cancel (task, TRUE);
1642 g_signal_connect (task, "notify::completed",
1643 (GCallback) completed_cb, &notification_emitted);
1645 g_task_set_task_data (task, (gpointer)&state, NULL);
1646 g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1647 g_object_unref (task);
1649 g_assert_cmpint (state, ==, 0);
1651 while (state == 0)
1652 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1653 g_assert (state == 1);
1655 while (state == 1)
1656 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1657 g_assert (state == 2);
1659 while (state == 2)
1660 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1661 g_assert (state == 4);
1663 while (state == 4)
1664 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1665 g_assert (state == 6);
1667 /* callback assumes there'll be a cancelled error */
1668 g_cancellable_cancel (cancellable);
1670 g_assert (callback_ran == FALSE);
1671 g_main_loop_run (loop);
1672 g_assert (callback_ran == TRUE);
1673 g_assert_true (notification_emitted);
1675 g_cancellable_reset (cancellable);
1678 /* If we cancel while it's temporarily not return-on-cancel, the
1679 * task won't complete right away, and further
1680 * g_task_set_return_on_cancel() calls will return FALSE.
1682 state = 0;
1683 callback_ran = FALSE;
1684 notification_emitted = FALSE;
1685 task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1686 g_task_set_return_on_cancel (task, TRUE);
1687 g_signal_connect (task, "notify::completed",
1688 (GCallback) completed_cb, &notification_emitted);
1690 g_task_set_task_data (task, (gpointer)&state, NULL);
1691 g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1692 g_object_unref (task);
1694 g_assert_cmpint (state, ==, 0);
1696 while (state == 0)
1697 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1698 g_assert (state == 1);
1699 g_assert (g_task_get_return_on_cancel (task));
1701 while (state == 1)
1702 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1703 g_assert (state == 2);
1704 g_assert (!g_task_get_return_on_cancel (task));
1706 g_cancellable_cancel (cancellable);
1707 g_idle_add (idle_quit_loop, NULL);
1708 g_main_loop_run (loop);
1709 g_assert (callback_ran == FALSE);
1711 while (state == 2)
1712 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1713 g_assert (state == 5);
1714 g_assert (!g_task_get_return_on_cancel (task));
1716 g_main_loop_run (loop);
1717 g_assert (callback_ran == TRUE);
1718 g_assert_true (notification_emitted);
1720 while (state == 5)
1721 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1722 g_assert (state == 7);
1724 g_object_unref (cancellable);
1725 g_mutex_unlock (&roca_mutex_1);
1726 g_mutex_unlock (&roca_mutex_2);
1729 /* test_return_pointer: memory management of pointer returns */
1731 static void
1732 test_return_pointer (void)
1734 GObject *object, *ret;
1735 GTask *task;
1736 GCancellable *cancellable;
1737 GError *error = NULL;
1739 /* If we don't read back the return value, the task will
1740 * run its destroy notify.
1742 object = (GObject *)g_dummy_object_new ();
1743 g_assert_cmpint (object->ref_count, ==, 1);
1744 g_object_add_weak_pointer (object, (gpointer *)&object);
1746 task = g_task_new (NULL, NULL, NULL, NULL);
1747 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1748 g_task_return_pointer (task, object, g_object_unref);
1749 g_assert_cmpint (object->ref_count, ==, 1);
1751 /* Task and object are reffed until the :completed notification in idle. */
1752 g_object_unref (task);
1753 g_assert_nonnull (task);
1754 g_assert_nonnull (object);
1756 wait_for_completed_notification (task);
1758 g_assert_null (task);
1759 g_assert_null (object);
1761 /* Likewise, if the return value is overwritten by an error */
1762 object = (GObject *)g_dummy_object_new ();
1763 g_assert_cmpint (object->ref_count, ==, 1);
1764 g_object_add_weak_pointer (object, (gpointer *)&object);
1766 cancellable = g_cancellable_new ();
1767 task = g_task_new (NULL, cancellable, NULL, NULL);
1768 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1769 g_task_return_pointer (task, object, g_object_unref);
1770 g_assert_cmpint (object->ref_count, ==, 1);
1771 g_cancellable_cancel (cancellable);
1772 g_assert_cmpint (object->ref_count, ==, 1);
1774 ret = g_task_propagate_pointer (task, &error);
1775 g_assert (ret == NULL);
1776 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1777 g_clear_error (&error);
1778 g_assert_cmpint (object->ref_count, ==, 1);
1780 g_object_unref (task);
1781 g_object_unref (cancellable);
1782 g_assert_nonnull (task);
1783 g_assert_nonnull (object);
1785 wait_for_completed_notification (task);
1787 g_assert_null (task);
1788 g_assert_null (object);
1790 /* If we read back the return value, we steal its ref */
1791 object = (GObject *)g_dummy_object_new ();
1792 g_assert_cmpint (object->ref_count, ==, 1);
1793 g_object_add_weak_pointer (object, (gpointer *)&object);
1795 task = g_task_new (NULL, NULL, NULL, NULL);
1796 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1797 g_task_return_pointer (task, object, g_object_unref);
1798 g_assert_cmpint (object->ref_count, ==, 1);
1800 ret = g_task_propagate_pointer (task, &error);
1801 g_assert_no_error (error);
1802 g_assert (ret == object);
1803 g_assert_cmpint (object->ref_count, ==, 1);
1805 g_object_unref (task);
1806 g_assert_nonnull (task);
1807 g_assert_cmpint (object->ref_count, ==, 1);
1808 g_object_unref (object);
1809 g_assert (object == NULL);
1811 wait_for_completed_notification (task);
1812 g_assert_null (task);
1815 /* test_object_keepalive: GTask takes a ref on its source object */
1817 static GObject *keepalive_object;
1819 static void
1820 keepalive_callback (GObject *object,
1821 GAsyncResult *result,
1822 gpointer user_data)
1824 gssize *result_out = user_data;
1825 GError *error = NULL;
1827 g_assert (object == keepalive_object);
1828 g_assert (g_task_is_valid (result, object));
1829 g_assert (g_async_result_get_user_data (result) == user_data);
1830 g_assert (!g_task_had_error (G_TASK (result)));
1831 g_assert_false (g_task_get_completed (G_TASK (result)));
1833 *result_out = g_task_propagate_int (G_TASK (result), &error);
1834 g_assert_no_error (error);
1836 g_assert (!g_task_had_error (G_TASK (result)));
1838 g_main_loop_quit (loop);
1841 static void
1842 test_object_keepalive (void)
1844 GObject *object;
1845 GTask *task;
1846 gssize result;
1847 int ref_count;
1848 gboolean notification_emitted = FALSE;
1850 keepalive_object = object = (GObject *)g_dummy_object_new ();
1851 g_object_add_weak_pointer (object, (gpointer *)&object);
1853 task = g_task_new (object, NULL, keepalive_callback, &result);
1854 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1855 g_signal_connect (task, "notify::completed",
1856 (GCallback) completed_cb, &notification_emitted);
1858 ref_count = object->ref_count;
1859 g_assert_cmpint (ref_count, >, 1);
1861 g_assert (g_task_get_source_object (task) == object);
1862 g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
1863 g_assert_cmpint (object->ref_count, ==, ref_count + 1);
1864 g_object_unref (object);
1866 g_object_unref (object);
1867 g_assert (object != NULL);
1869 g_task_return_int (task, magic);
1870 g_main_loop_run (loop);
1872 g_assert (object != NULL);
1873 g_assert_cmpint (result, ==, magic);
1874 g_assert_true (notification_emitted);
1876 g_object_unref (task);
1877 g_assert (task == NULL);
1878 g_assert (object == NULL);
1881 /* test_legacy_error: legacy GSimpleAsyncResult handling */
1882 static void test_legacy_error (void);
1884 static void
1885 legacy_error_callback (GObject *object,
1886 GAsyncResult *result,
1887 gpointer user_data)
1889 gssize *result_out = user_data;
1890 GError *error = NULL;
1892 g_assert (object == NULL);
1893 g_assert (g_async_result_is_tagged (result, test_legacy_error));
1894 g_assert (g_async_result_get_user_data (result) == user_data);
1896 if (g_async_result_legacy_propagate_error (result, &error))
1898 g_assert (!g_task_is_valid (result, object));
1899 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1900 g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
1901 G_GNUC_END_IGNORE_DEPRECATIONS;
1903 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1904 *result_out = -2;
1906 else
1908 g_assert (g_task_is_valid (result, object));
1910 *result_out = g_task_propagate_int (G_TASK (result), NULL);
1911 /* Might be error, might not */
1914 g_main_loop_quit (loop);
1917 static gboolean
1918 legacy_error_return (gpointer user_data)
1920 if (G_IS_TASK (user_data))
1922 GTask *task = user_data;
1924 g_task_return_int (task, magic);
1925 g_object_unref (task);
1927 else
1929 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
1931 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1932 g_simple_async_result_set_error (simple,
1933 G_IO_ERROR,
1934 G_IO_ERROR_FAILED,
1935 "Failed");
1936 g_simple_async_result_complete (simple);
1937 G_GNUC_END_IGNORE_DEPRECATIONS;
1938 g_object_unref (simple);
1941 return FALSE;
1944 static void
1945 test_legacy_error (void)
1947 GTask *task;
1948 GSimpleAsyncResult *simple;
1949 gssize result;
1951 /* GTask success */
1952 task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1953 g_task_set_source_tag (task, test_legacy_error);
1954 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1956 g_idle_add (legacy_error_return, task);
1957 g_main_loop_run (loop);
1959 g_assert_cmpint (result, ==, magic);
1960 g_assert (task == NULL);
1962 /* GTask error */
1963 task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1964 g_task_set_source_tag (task, test_legacy_error);
1965 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1967 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
1968 "Failed");
1969 g_object_unref (task);
1970 g_main_loop_run (loop);
1972 g_assert_cmpint (result, ==, -1);
1973 g_assert (task == NULL);
1975 /* GSimpleAsyncResult error */
1976 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1977 simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
1978 test_legacy_error);
1979 G_GNUC_END_IGNORE_DEPRECATIONS;
1980 g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
1982 g_idle_add (legacy_error_return, simple);
1983 g_main_loop_run (loop);
1985 g_assert_cmpint (result, ==, -2);
1986 g_assert (simple == NULL);
1991 main (int argc, char **argv)
1993 int ret;
1995 g_test_init (&argc, &argv, NULL);
1997 loop = g_main_loop_new (NULL, FALSE);
1998 main_thread = g_thread_self ();
1999 magic = g_get_monotonic_time ();
2001 g_test_add_func ("/gtask/basic", test_basic);
2002 g_test_add_func ("/gtask/error", test_error);
2003 g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
2004 g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
2005 g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
2006 g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
2007 g_test_add_func ("/gtask/no-callback", test_no_callback);
2008 g_test_add_func ("/gtask/report-error", test_report_error);
2009 g_test_add_func ("/gtask/priority", test_priority);
2010 g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
2011 g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
2012 g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
2013 g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
2014 g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
2015 g_test_add_func ("/gtask/run-in-thread-nested", test_run_in_thread_nested);
2016 g_test_add_func ("/gtask/run-in-thread-overflow", test_run_in_thread_overflow);
2017 g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
2018 g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
2019 g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
2020 g_test_add_func ("/gtask/return-pointer", test_return_pointer);
2021 g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
2022 g_test_add_func ("/gtask/legacy-error", test_legacy_error);
2024 ret = g_test_run();
2026 g_main_loop_unref (loop);
2028 return ret;