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.
14 static GMainLoop *loop;
15 static GThread *main_thread;
18 /* We need objects for a few tests where we don't care what type
19 * they are, just that they're GObjects.
21 #define g_dummy_object_new g_socket_client_new
26 basic_callback (GObject *object,
30 gssize *result_out = user_data;
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)));
38 *result_out = g_task_propagate_int (G_TASK (result), &error);
39 g_assert_no_error (error);
41 g_main_loop_quit (loop);
45 basic_return (gpointer user_data)
47 GTask *task = user_data;
49 g_task_return_int (task, magic);
50 g_object_unref (task);
56 basic_destroy_notify (gpointer user_data)
58 gboolean *destroyed = user_data;
68 gboolean task_data_destroyed = FALSE;
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);
74 g_idle_add (basic_return, task);
75 g_main_loop_run (loop);
77 g_assert_cmpint (result, ==, magic);
78 g_assert (task_data_destroyed == TRUE);
79 g_assert (task == NULL);
85 error_callback (GObject *object,
89 gssize *result_out = user_data;
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)));
97 *result_out = g_task_propagate_int (G_TASK (result), &error);
98 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
101 g_main_loop_quit (loop);
105 error_return (gpointer user_data)
107 GTask *task = user_data;
109 g_task_return_new_error (task,
110 G_IO_ERROR, G_IO_ERROR_FAILED,
112 g_object_unref (task);
118 error_destroy_notify (gpointer user_data)
120 gboolean *destroyed = user_data;
130 gboolean first_task_data_destroyed = FALSE;
131 gboolean second_task_data_destroyed = FALSE;
133 task = g_task_new (NULL, NULL, error_callback, &result);
134 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
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);
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);
145 g_idle_add (error_return, task);
146 g_main_loop_run (loop);
148 g_assert_cmpint (result, ==, -1);
149 g_assert (second_task_data_destroyed == TRUE);
150 g_assert (task == NULL);
153 /* test_return_from_same_iteration: calling g_task_return_* from the
154 * loop iteration the task was created in defers completion until the
157 gboolean same_result = FALSE;
160 same_callback (GObject *object,
161 GAsyncResult *result,
164 gboolean *result_out = user_data;
165 GError *error = NULL;
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)));
172 *result_out = g_task_propagate_boolean (G_TASK (result), &error);
173 g_assert_no_error (error);
175 g_main_loop_quit (loop);
179 same_start (gpointer user_data)
181 gpointer *weak_pointer = user_data;
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);
188 g_task_return_boolean (task, TRUE);
189 g_object_unref (task);
191 /* same_callback should not have been invoked yet */
192 g_assert (same_result == FALSE);
193 g_assert (*weak_pointer == task);
199 test_return_from_same_iteration (void)
201 gpointer weak_pointer;
203 g_idle_add (same_start, &weak_pointer);
204 g_main_loop_run (loop);
206 g_assert (same_result == TRUE);
207 g_assert (weak_pointer == NULL);
210 /* test_return_from_toplevel: calling g_task_return_* from outside any
211 * main loop completes the task inside the main loop.
215 toplevel_callback (GObject *object,
216 GAsyncResult *result,
219 gboolean *result_out = user_data;
220 GError *error = NULL;
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)));
227 *result_out = g_task_propagate_boolean (G_TASK (result), &error);
228 g_assert_no_error (error);
230 g_main_loop_quit (loop);
234 test_return_from_toplevel (void)
237 gboolean result = FALSE;
239 task = g_task_new (NULL, NULL, toplevel_callback, &result);
240 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
242 g_task_return_boolean (task, TRUE);
243 g_object_unref (task);
245 /* toplevel_callback should not have been invoked yet */
246 g_assert (result == FALSE);
247 g_assert (task != NULL);
249 g_main_loop_run (loop);
251 g_assert (result == TRUE);
252 g_assert (task == NULL);
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.
260 GThread *anon_thread;
263 anon_callback (GObject *object,
264 GAsyncResult *result,
267 gssize *result_out = user_data;
268 GError *error = NULL;
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)));
275 g_assert (g_thread_self () == main_thread);
277 *result_out = g_task_propagate_int (G_TASK (result), &error);
278 g_assert_no_error (error);
280 g_main_loop_quit (loop);
284 anon_thread_func (gpointer user_data)
286 GTask *task = user_data;
288 g_task_return_int (task, magic);
289 g_object_unref (task);
295 anon_start (gpointer user_data)
297 GTask *task = user_data;
299 anon_thread = g_thread_new ("test_return_from_anon_thread",
300 anon_thread_func, task);
305 test_return_from_anon_thread (void)
310 task = g_task_new (NULL, NULL, anon_callback, &result);
311 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
313 g_idle_add (anon_start, task);
314 g_main_loop_run (loop);
316 g_thread_join (anon_thread);
318 g_assert_cmpint (result, ==, magic);
319 g_assert (task == NULL);
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.
327 GThread *wrong_thread;
330 wrong_callback (GObject *object,
331 GAsyncResult *result,
334 gssize *result_out = user_data;
335 GError *error = NULL;
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)));
342 g_assert (g_thread_self () == main_thread);
344 *result_out = g_task_propagate_int (G_TASK (result), &error);
345 g_assert_no_error (error);
347 g_main_loop_quit (loop);
351 wrong_thread_func (gpointer user_data)
353 GTask *task = user_data;
354 GMainContext *context;
356 context = g_main_context_new ();
357 g_main_context_push_thread_default (context);
359 g_assert (g_task_get_context (task) != context);
361 g_task_return_int (task, magic);
362 g_object_unref (task);
364 g_main_context_pop_thread_default (context);
365 g_main_context_unref (context);
371 wrong_start (gpointer user_data)
373 GTask *task = user_data;
375 wrong_thread = g_thread_new ("test_return_from_anon_thread",
376 wrong_thread_func, task);
381 test_return_from_wrong_thread (void)
386 task = g_task_new (NULL, NULL, wrong_callback, &result);
387 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
389 g_idle_add (wrong_start, task);
390 g_main_loop_run (loop);
392 g_thread_join (wrong_thread);
394 g_assert_cmpint (result, ==, magic);
395 g_assert (task == NULL);
398 /* test_no_callback */
401 test_no_callback (void)
405 task = g_task_new (NULL, NULL, NULL, NULL);
406 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
408 g_task_return_boolean (task, TRUE);
409 g_object_unref (task);
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.
415 g_assert (task == NULL);
418 /* test_report_error */
420 static void test_report_error (void);
423 report_callback (GObject *object,
424 GAsyncResult *result,
427 gpointer *weak_pointer = user_data;
428 GError *error = NULL;
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)));
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);
443 *weak_pointer = result;
444 g_object_add_weak_pointer (G_OBJECT (result), weak_pointer);
446 g_main_loop_quit (loop);
450 test_report_error (void)
452 gpointer weak_pointer = (gpointer)-1;
454 g_task_report_new_error (NULL, report_callback, &weak_pointer,
456 G_IO_ERROR, G_IO_ERROR_FAILED,
458 g_main_loop_run (loop);
460 g_assert (weak_pointer == NULL);
463 /* test_priority: tasks complete in priority order */
465 static int counter = 0;
468 priority_callback (GObject *object,
469 GAsyncResult *result,
472 gssize *ret_out = user_data;
473 GError *error = NULL;
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)));
480 g_task_propagate_boolean (G_TASK (result), &error);
481 g_assert_no_error (error);
483 *ret_out = ++counter;
486 g_main_loop_quit (loop);
493 gssize ret1, ret2, ret3;
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).
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);
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);
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);
515 g_main_loop_run (loop);
517 g_assert_cmpint (ret2, ==, 1);
518 g_assert_cmpint (ret1, ==, 2);
519 g_assert_cmpint (ret3, ==, 3);
522 /* test_check_cancellable: cancellation overrides return value */
525 CANCEL_BEFORE = (1 << 1),
526 CANCEL_AFTER = (1 << 2),
527 CHECK_CANCELLABLE = (1 << 3)
529 #define NUM_CANCEL_TESTS (CANCEL_BEFORE | CANCEL_AFTER | CHECK_CANCELLABLE)
532 cancel_callback (GObject *object,
533 GAsyncResult *result,
536 int state = GPOINTER_TO_INT (user_data);
538 GCancellable *cancellable;
539 GError *error = NULL;
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);
545 task = G_TASK (result);
546 cancellable = g_task_get_cancellable (task);
547 g_assert (G_IS_CANCELLABLE (cancellable));
549 if (state & (CANCEL_BEFORE | CANCEL_AFTER))
550 g_assert (g_cancellable_is_cancelled (cancellable));
552 g_assert (!g_cancellable_is_cancelled (cancellable));
554 if (state & CHECK_CANCELLABLE)
555 g_assert (g_task_get_check_cancellable (task));
557 g_assert (!g_task_get_check_cancellable (task));
559 if (g_task_propagate_boolean (task, &error))
561 g_assert (!g_cancellable_is_cancelled (cancellable) ||
562 !g_task_get_check_cancellable (task));
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);
572 g_main_loop_quit (loop);
576 test_check_cancellable (void)
579 GCancellable *cancellable;
582 cancellable = g_cancellable_new ();
584 for (state = 0; state <= NUM_CANCEL_TESTS; state++)
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);
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);
596 g_main_loop_run (loop);
597 g_object_unref (task);
598 g_cancellable_reset (cancellable);
601 g_object_unref (cancellable);
604 /* test_return_if_cancelled */
607 return_if_cancelled_callback (GObject *object,
608 GAsyncResult *result,
611 GError *error = NULL;
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)));
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);
622 g_main_loop_quit (loop);
626 test_return_if_cancelled (void)
629 GCancellable *cancellable;
632 cancellable = g_cancellable_new ();
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);
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);
652 /* test_run_in_thread */
655 run_in_thread_callback (GObject *object,
656 GAsyncResult *result,
659 gboolean *done = user_data;
660 GError *error = NULL;
663 g_assert (g_thread_self () == main_thread);
665 g_assert (object == NULL);
666 g_assert (g_task_is_valid (result, object));
667 g_assert (g_async_result_get_user_data (result) == user_data);
668 g_assert (!g_task_had_error (G_TASK (result)));
670 ret = g_task_propagate_int (G_TASK (result), &error);
671 g_assert_no_error (error);
672 g_assert_cmpint (ret, ==, magic);
675 g_main_loop_quit (loop);
679 run_in_thread_thread (GTask *task,
680 gpointer source_object,
682 GCancellable *cancellable)
684 gboolean *thread_ran = task_data;
686 g_assert (source_object == g_task_get_source_object (task));
687 g_assert (task_data == g_task_get_task_data (task));
688 g_assert (cancellable == g_task_get_cancellable (task));
690 g_assert (g_thread_self () != main_thread);
693 g_task_return_int (task, magic);
697 test_run_in_thread (void)
700 volatile gboolean thread_ran = FALSE;
701 gboolean done = FALSE;
703 task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
704 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
706 g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
707 g_task_run_in_thread (task, run_in_thread_thread);
708 g_object_unref (task);
713 g_assert (done == FALSE);
714 g_assert (task != NULL);
716 g_main_loop_run (loop);
718 g_assert (done == TRUE);
719 g_assert (task == NULL);
722 /* test_run_in_thread_sync */
725 run_in_thread_sync_callback (GObject *object,
726 GAsyncResult *result,
729 /* g_task_run_in_thread_sync() does not invoke the task's callback */
730 g_assert_not_reached ();
734 run_in_thread_sync_thread (GTask *task,
735 gpointer source_object,
737 GCancellable *cancellable)
739 gboolean *thread_ran = task_data;
741 g_assert (source_object == g_task_get_source_object (task));
742 g_assert (task_data == g_task_get_task_data (task));
743 g_assert (cancellable == g_task_get_cancellable (task));
745 g_assert (g_thread_self () != main_thread);
748 g_task_return_int (task, magic);
752 test_run_in_thread_sync (void)
755 gboolean thread_ran = FALSE;
757 GError *error = NULL;
759 task = g_task_new (NULL, NULL, run_in_thread_sync_callback, NULL);
761 g_task_set_task_data (task, &thread_ran, NULL);
762 g_task_run_in_thread_sync (task, run_in_thread_sync_thread);
764 g_assert (thread_ran == TRUE);
765 g_assert (task != NULL);
766 g_assert (!g_task_had_error (task));
768 ret = g_task_propagate_int (task, &error);
769 g_assert_no_error (error);
770 g_assert_cmpint (ret, ==, magic);
772 g_object_unref (task);
775 /* test_run_in_thread_priority */
777 static GMutex fake_task_mutex, last_fake_task_mutex;
778 static gint sequence_number = 0;
781 quit_main_loop_callback (GObject *object,
782 GAsyncResult *result,
785 GError *error = NULL;
788 g_assert (g_thread_self () == main_thread);
790 g_assert (object == NULL);
791 g_assert (g_task_is_valid (result, object));
792 g_assert (g_async_result_get_user_data (result) == user_data);
793 g_assert (!g_task_had_error (G_TASK (result)));
795 ret = g_task_propagate_boolean (G_TASK (result), &error);
796 g_assert_no_error (error);
797 g_assert_cmpint (ret, ==, TRUE);
799 g_main_loop_quit (loop);
803 set_sequence_number_thread (GTask *task,
804 gpointer source_object,
806 GCancellable *cancellable)
808 gint *seq_no_p = task_data;
810 *seq_no_p = ++sequence_number;
811 g_task_return_boolean (task, TRUE);
815 fake_task_thread (GTask *task,
816 gpointer source_object,
818 GCancellable *cancellable)
820 GMutex *mutex = task_data;
822 g_mutex_lock (mutex);
823 g_mutex_unlock (mutex);
824 g_task_return_boolean (task, TRUE);
827 #define G_TASK_THREAD_POOL_SIZE 100
830 test_run_in_thread_priority (void)
833 GCancellable *cancellable;
834 int seq_a, seq_b, seq_c, seq_d;
837 /* Flush the thread pool, then clog it up with junk tasks */
838 g_thread_pool_stop_unused_threads ();
840 g_mutex_lock (&fake_task_mutex);
841 for (i = 0; i < G_TASK_THREAD_POOL_SIZE - 1; i++)
843 task = g_task_new (NULL, NULL, NULL, NULL);
844 g_task_set_task_data (task, &fake_task_mutex, NULL);
845 g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_DEFAULT);
846 g_task_set_priority (task, G_PRIORITY_HIGH * 2);
847 g_assert_cmpint (g_task_get_priority (task), ==, G_PRIORITY_HIGH * 2);
848 g_task_run_in_thread (task, fake_task_thread);
849 g_object_unref (task);
852 g_mutex_lock (&last_fake_task_mutex);
853 task = g_task_new (NULL, NULL, NULL, NULL);
854 g_task_set_task_data (task, &last_fake_task_mutex, NULL);
855 g_task_set_priority (task, G_PRIORITY_HIGH * 2);
856 g_task_run_in_thread (task, fake_task_thread);
857 g_object_unref (task);
859 /* Queue three more tasks that we'll arrange to have run serially */
860 task = g_task_new (NULL, NULL, NULL, NULL);
861 g_task_set_task_data (task, &seq_a, NULL);
862 g_task_run_in_thread (task, set_sequence_number_thread);
863 g_object_unref (task);
865 task = g_task_new (NULL, NULL, quit_main_loop_callback, NULL);
866 g_task_set_task_data (task, &seq_b, NULL);
867 g_task_set_priority (task, G_PRIORITY_LOW);
868 g_task_run_in_thread (task, set_sequence_number_thread);
869 g_object_unref (task);
871 task = g_task_new (NULL, NULL, NULL, NULL);
872 g_task_set_task_data (task, &seq_c, NULL);
873 g_task_set_priority (task, G_PRIORITY_HIGH);
874 g_task_run_in_thread (task, set_sequence_number_thread);
875 g_object_unref (task);
877 cancellable = g_cancellable_new ();
878 task = g_task_new (NULL, cancellable, NULL, NULL);
879 g_task_set_task_data (task, &seq_d, NULL);
880 g_task_run_in_thread (task, set_sequence_number_thread);
881 g_cancellable_cancel (cancellable);
882 g_object_unref (cancellable);
883 g_object_unref (task);
885 /* Let the last fake task complete; the four other tasks will then
886 * complete serially, in the order D, C, A, B, and B will quit the
889 g_mutex_unlock (&last_fake_task_mutex);
890 g_main_loop_run (loop);
892 g_assert_cmpint (seq_d, ==, 1);
893 g_assert_cmpint (seq_c, ==, 2);
894 g_assert_cmpint (seq_a, ==, 3);
895 g_assert_cmpint (seq_b, ==, 4);
897 g_mutex_unlock (&fake_task_mutex);
900 /* test_return_on_cancel */
902 GMutex roc_init_mutex, roc_finish_mutex;
903 GCond roc_init_cond, roc_finish_cond;
913 return_on_cancel_callback (GObject *object,
914 GAsyncResult *result,
917 gboolean *callback_ran = user_data;
918 GError *error = NULL;
921 g_assert (g_thread_self () == main_thread);
923 g_assert (object == NULL);
924 g_assert (g_task_is_valid (result, object));
925 g_assert (g_async_result_get_user_data (result) == user_data);
926 g_assert (g_task_had_error (G_TASK (result)));
928 ret = g_task_propagate_int (G_TASK (result), &error);
929 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
930 g_clear_error (&error);
931 g_assert_cmpint (ret, ==, -1);
933 *callback_ran = TRUE;
934 g_main_loop_quit (loop);
938 return_on_cancel_thread (GTask *task,
939 gpointer source_object,
941 GCancellable *cancellable)
943 ThreadState *state = task_data;
945 g_assert (source_object == g_task_get_source_object (task));
946 g_assert (task_data == g_task_get_task_data (task));
947 g_assert (cancellable == g_task_get_cancellable (task));
949 g_assert (g_thread_self () != main_thread);
951 g_mutex_lock (&roc_init_mutex);
952 *state = THREAD_RUNNING;
953 g_cond_signal (&roc_init_cond);
954 g_mutex_unlock (&roc_init_mutex);
956 g_mutex_lock (&roc_finish_mutex);
958 if (!g_task_get_return_on_cancel (task) ||
959 g_task_set_return_on_cancel (task, FALSE))
961 *state = THREAD_COMPLETED;
962 g_task_return_int (task, magic);
965 *state = THREAD_CANCELLED;
967 g_cond_signal (&roc_finish_cond);
968 g_mutex_unlock (&roc_finish_mutex);
972 test_return_on_cancel (void)
975 GCancellable *cancellable;
976 volatile ThreadState thread_state;
977 gboolean callback_ran;
979 cancellable = g_cancellable_new ();
981 /* If return-on-cancel is FALSE (default), the task does not return
984 callback_ran = FALSE;
985 thread_state = THREAD_STARTING;
986 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
988 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
989 g_mutex_lock (&roc_init_mutex);
990 g_mutex_lock (&roc_finish_mutex);
991 g_task_run_in_thread (task, return_on_cancel_thread);
992 g_object_unref (task);
994 while (thread_state == THREAD_STARTING)
995 g_cond_wait (&roc_init_cond, &roc_init_mutex);
996 g_mutex_unlock (&roc_init_mutex);
998 g_assert (thread_state == THREAD_RUNNING);
999 g_assert (callback_ran == FALSE);
1001 g_cancellable_cancel (cancellable);
1002 g_mutex_unlock (&roc_finish_mutex);
1003 g_main_loop_run (loop);
1005 g_assert (thread_state == THREAD_COMPLETED);
1006 g_assert (callback_ran == TRUE);
1008 g_cancellable_reset (cancellable);
1010 /* If return-on-cancel is TRUE, it does return early */
1011 callback_ran = FALSE;
1012 thread_state = THREAD_STARTING;
1013 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1014 g_task_set_return_on_cancel (task, TRUE);
1016 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1017 g_mutex_lock (&roc_init_mutex);
1018 g_mutex_lock (&roc_finish_mutex);
1019 g_task_run_in_thread (task, return_on_cancel_thread);
1020 g_object_unref (task);
1022 while (thread_state == THREAD_STARTING)
1023 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1024 g_mutex_unlock (&roc_init_mutex);
1026 g_assert (thread_state == THREAD_RUNNING);
1027 g_assert (callback_ran == FALSE);
1029 g_cancellable_cancel (cancellable);
1030 g_main_loop_run (loop);
1031 g_assert (thread_state == THREAD_RUNNING);
1032 g_assert (callback_ran == TRUE);
1034 while (thread_state == THREAD_RUNNING)
1035 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1036 g_mutex_unlock (&roc_finish_mutex);
1038 g_assert (thread_state == THREAD_CANCELLED);
1039 /* We can't g_assert (task == NULL) here because it won't become NULL
1040 * until a little bit after roc_finish_cond is signaled.
1043 g_cancellable_reset (cancellable);
1045 /* If the task is already cancelled before it starts, it returns
1046 * immediately, but the thread func still runs.
1048 callback_ran = FALSE;
1049 thread_state = THREAD_STARTING;
1050 task = g_task_new (NULL, cancellable, return_on_cancel_callback, &callback_ran);
1051 g_task_set_return_on_cancel (task, TRUE);
1053 g_cancellable_cancel (cancellable);
1055 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1056 g_mutex_lock (&roc_init_mutex);
1057 g_mutex_lock (&roc_finish_mutex);
1058 g_task_run_in_thread (task, return_on_cancel_thread);
1059 g_object_unref (task);
1061 g_main_loop_run (loop);
1062 g_assert (callback_ran == TRUE);
1064 while (thread_state == THREAD_STARTING)
1065 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1066 g_mutex_unlock (&roc_init_mutex);
1068 g_assert (thread_state == THREAD_RUNNING);
1070 while (thread_state == THREAD_RUNNING)
1071 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1072 g_mutex_unlock (&roc_finish_mutex);
1074 g_assert (thread_state == THREAD_CANCELLED);
1076 g_object_unref (cancellable);
1079 /* test_return_on_cancel_sync */
1082 cancel_sync_runner_thread (gpointer task)
1084 g_task_run_in_thread_sync (task, return_on_cancel_thread);
1089 test_return_on_cancel_sync (void)
1092 GCancellable *cancellable;
1093 volatile ThreadState thread_state;
1094 GThread *runner_thread;
1096 GError *error = NULL;
1098 cancellable = g_cancellable_new ();
1100 /* If return-on-cancel is FALSE, the task does not return early.
1102 thread_state = THREAD_STARTING;
1103 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1105 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1106 g_mutex_lock (&roc_init_mutex);
1107 g_mutex_lock (&roc_finish_mutex);
1108 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1109 cancel_sync_runner_thread, task);
1111 while (thread_state == THREAD_STARTING)
1112 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1113 g_mutex_unlock (&roc_init_mutex);
1115 g_assert (thread_state == THREAD_RUNNING);
1117 g_cancellable_cancel (cancellable);
1118 g_mutex_unlock (&roc_finish_mutex);
1119 g_thread_join (runner_thread);
1120 g_assert (thread_state == THREAD_COMPLETED);
1122 ret = g_task_propagate_int (task, &error);
1123 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1124 g_clear_error (&error);
1125 g_assert_cmpint (ret, ==, -1);
1127 g_object_unref (task);
1129 g_cancellable_reset (cancellable);
1131 /* If return-on-cancel is TRUE, it does return early */
1132 thread_state = THREAD_STARTING;
1133 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1134 g_task_set_return_on_cancel (task, TRUE);
1136 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1137 g_mutex_lock (&roc_init_mutex);
1138 g_mutex_lock (&roc_finish_mutex);
1139 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1140 cancel_sync_runner_thread, task);
1142 while (thread_state == THREAD_STARTING)
1143 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1144 g_mutex_unlock (&roc_init_mutex);
1146 g_assert (thread_state == THREAD_RUNNING);
1148 g_cancellable_cancel (cancellable);
1149 g_thread_join (runner_thread);
1150 g_assert (thread_state == THREAD_RUNNING);
1152 ret = g_task_propagate_int (task, &error);
1153 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1154 g_clear_error (&error);
1155 g_assert_cmpint (ret, ==, -1);
1157 g_object_unref (task);
1159 while (thread_state == THREAD_RUNNING)
1160 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1161 g_mutex_unlock (&roc_finish_mutex);
1163 g_assert (thread_state == THREAD_CANCELLED);
1165 g_cancellable_reset (cancellable);
1167 /* If the task is already cancelled before it starts, it returns
1168 * immediately, but the thread func still runs.
1170 thread_state = THREAD_STARTING;
1171 task = g_task_new (NULL, cancellable, run_in_thread_sync_callback, NULL);
1172 g_task_set_return_on_cancel (task, TRUE);
1174 g_cancellable_cancel (cancellable);
1176 g_task_set_task_data (task, (gpointer)&thread_state, NULL);
1177 g_mutex_lock (&roc_init_mutex);
1178 g_mutex_lock (&roc_finish_mutex);
1179 runner_thread = g_thread_new ("return-on-cancel-sync runner thread",
1180 cancel_sync_runner_thread, task);
1182 g_thread_join (runner_thread);
1183 g_assert (thread_state == THREAD_STARTING);
1185 ret = g_task_propagate_int (task, &error);
1186 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1187 g_clear_error (&error);
1188 g_assert_cmpint (ret, ==, -1);
1190 g_object_unref (task);
1192 while (thread_state == THREAD_STARTING)
1193 g_cond_wait (&roc_init_cond, &roc_init_mutex);
1194 g_mutex_unlock (&roc_init_mutex);
1196 g_assert (thread_state == THREAD_RUNNING);
1198 while (thread_state == THREAD_RUNNING)
1199 g_cond_wait (&roc_finish_cond, &roc_finish_mutex);
1200 g_mutex_unlock (&roc_finish_mutex);
1202 g_assert (thread_state == THREAD_CANCELLED);
1204 g_object_unref (cancellable);
1207 /* test_return_on_cancel_atomic: turning return-on-cancel on/off is
1211 GMutex roca_mutex_1, roca_mutex_2;
1212 GCond roca_cond_1, roca_cond_2;
1215 return_on_cancel_atomic_callback (GObject *object,
1216 GAsyncResult *result,
1219 gboolean *callback_ran = user_data;
1220 GError *error = NULL;
1223 g_assert (g_thread_self () == main_thread);
1225 g_assert (object == NULL);
1226 g_assert (g_task_is_valid (result, object));
1227 g_assert (g_async_result_get_user_data (result) == user_data);
1228 g_assert (g_task_had_error (G_TASK (result)));
1230 ret = g_task_propagate_int (G_TASK (result), &error);
1231 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1232 g_clear_error (&error);
1233 g_assert_cmpint (ret, ==, -1);
1235 *callback_ran = TRUE;
1236 g_main_loop_quit (loop);
1240 idle_quit_loop (gpointer user_data)
1242 g_main_loop_quit (loop);
1247 return_on_cancel_atomic_thread (GTask *task,
1248 gpointer source_object,
1250 GCancellable *cancellable)
1252 gint *state = task_data;
1254 g_assert (source_object == g_task_get_source_object (task));
1255 g_assert (task_data == g_task_get_task_data (task));
1256 g_assert (cancellable == g_task_get_cancellable (task));
1258 g_assert (g_thread_self () != main_thread);
1259 g_assert_cmpint (*state, ==, 0);
1261 g_mutex_lock (&roca_mutex_1);
1263 g_cond_signal (&roca_cond_1);
1264 g_mutex_unlock (&roca_mutex_1);
1266 g_mutex_lock (&roca_mutex_2);
1267 if (g_task_set_return_on_cancel (task, FALSE))
1271 g_cond_signal (&roca_cond_2);
1272 g_mutex_unlock (&roca_mutex_2);
1274 g_mutex_lock (&roca_mutex_1);
1275 if (g_task_set_return_on_cancel (task, TRUE))
1279 g_cond_signal (&roca_cond_1);
1280 g_mutex_unlock (&roca_mutex_1);
1282 g_mutex_lock (&roca_mutex_2);
1283 if (g_task_set_return_on_cancel (task, TRUE))
1287 g_cond_signal (&roca_cond_2);
1288 g_mutex_unlock (&roca_mutex_2);
1290 g_task_return_int (task, magic);
1294 test_return_on_cancel_atomic (void)
1297 GCancellable *cancellable;
1298 volatile gint state;
1299 gboolean callback_ran;
1301 cancellable = g_cancellable_new ();
1302 g_mutex_lock (&roca_mutex_1);
1303 g_mutex_lock (&roca_mutex_2);
1305 /* If we don't cancel it, each set_return_on_cancel() call will succeed */
1307 callback_ran = FALSE;
1308 task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1309 g_task_set_return_on_cancel (task, TRUE);
1311 g_task_set_task_data (task, (gpointer)&state, NULL);
1312 g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1313 g_object_unref (task);
1315 g_assert_cmpint (state, ==, 0);
1318 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1319 g_assert (state == 1);
1322 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1323 g_assert (state == 2);
1326 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1327 g_assert (state == 4);
1330 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1331 g_assert (state == 6);
1333 /* callback assumes there'll be a cancelled error */
1334 g_cancellable_cancel (cancellable);
1336 g_assert (callback_ran == FALSE);
1337 g_main_loop_run (loop);
1338 g_assert (callback_ran == TRUE);
1340 g_cancellable_reset (cancellable);
1343 /* If we cancel while it's temporarily not return-on-cancel, the
1344 * task won't complete right away, and further
1345 * g_task_set_return_on_cancel() calls will return FALSE.
1348 callback_ran = FALSE;
1349 task = g_task_new (NULL, cancellable, return_on_cancel_atomic_callback, &callback_ran);
1350 g_task_set_return_on_cancel (task, TRUE);
1352 g_task_set_task_data (task, (gpointer)&state, NULL);
1353 g_task_run_in_thread (task, return_on_cancel_atomic_thread);
1354 g_object_unref (task);
1356 g_assert_cmpint (state, ==, 0);
1359 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1360 g_assert (state == 1);
1361 g_assert (g_task_get_return_on_cancel (task));
1364 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1365 g_assert (state == 2);
1366 g_assert (!g_task_get_return_on_cancel (task));
1368 g_cancellable_cancel (cancellable);
1369 g_idle_add (idle_quit_loop, NULL);
1370 g_main_loop_run (loop);
1371 g_assert (callback_ran == FALSE);
1374 g_cond_wait (&roca_cond_1, &roca_mutex_1);
1375 g_assert (state == 5);
1376 g_assert (!g_task_get_return_on_cancel (task));
1378 g_main_loop_run (loop);
1379 g_assert (callback_ran == TRUE);
1382 g_cond_wait (&roca_cond_2, &roca_mutex_2);
1383 g_assert (state == 7);
1385 g_object_unref (cancellable);
1386 g_mutex_unlock (&roca_mutex_1);
1387 g_mutex_unlock (&roca_mutex_2);
1390 /* test_return_pointer: memory management of pointer returns */
1393 test_return_pointer (void)
1395 GObject *object, *ret;
1397 GCancellable *cancellable;
1398 GError *error = NULL;
1400 /* If we don't read back the return value, the task will
1401 * run its destroy notify.
1403 object = (GObject *)g_dummy_object_new ();
1404 g_assert_cmpint (object->ref_count, ==, 1);
1405 g_object_add_weak_pointer (object, (gpointer *)&object);
1407 task = g_task_new (NULL, NULL, NULL, NULL);
1408 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1409 g_task_return_pointer (task, object, g_object_unref);
1410 g_assert_cmpint (object->ref_count, ==, 1);
1412 g_object_unref (task);
1413 g_assert (task == NULL);
1414 g_assert (object == NULL);
1416 /* Likewise, if the return value is overwritten by an error */
1417 object = (GObject *)g_dummy_object_new ();
1418 g_assert_cmpint (object->ref_count, ==, 1);
1419 g_object_add_weak_pointer (object, (gpointer *)&object);
1421 cancellable = g_cancellable_new ();
1422 task = g_task_new (NULL, cancellable, NULL, NULL);
1423 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1424 g_task_return_pointer (task, object, g_object_unref);
1425 g_assert_cmpint (object->ref_count, ==, 1);
1426 g_cancellable_cancel (cancellable);
1427 g_assert_cmpint (object->ref_count, ==, 1);
1429 ret = g_task_propagate_pointer (task, &error);
1430 g_assert (ret == NULL);
1431 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
1432 g_clear_error (&error);
1433 g_assert_cmpint (object->ref_count, ==, 1);
1435 g_object_unref (task);
1436 g_object_unref (cancellable);
1437 g_assert (task == NULL);
1438 g_assert (object == NULL);
1440 /* If we read back the return value, we steal its ref */
1441 object = (GObject *)g_dummy_object_new ();
1442 g_assert_cmpint (object->ref_count, ==, 1);
1443 g_object_add_weak_pointer (object, (gpointer *)&object);
1445 task = g_task_new (NULL, NULL, NULL, NULL);
1446 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1447 g_task_return_pointer (task, object, g_object_unref);
1448 g_assert_cmpint (object->ref_count, ==, 1);
1450 ret = g_task_propagate_pointer (task, &error);
1451 g_assert_no_error (error);
1452 g_assert (ret == object);
1453 g_assert_cmpint (object->ref_count, ==, 1);
1455 g_object_unref (task);
1456 g_assert (task == NULL);
1457 g_assert_cmpint (object->ref_count, ==, 1);
1458 g_object_unref (object);
1459 g_assert (object == NULL);
1462 /* test_object_keepalive: GTask takes a ref on its source object */
1464 static GObject *keepalive_object;
1467 keepalive_callback (GObject *object,
1468 GAsyncResult *result,
1471 gssize *result_out = user_data;
1472 GError *error = NULL;
1474 g_assert (object == keepalive_object);
1475 g_assert (g_task_is_valid (result, object));
1476 g_assert (g_async_result_get_user_data (result) == user_data);
1477 g_assert (!g_task_had_error (G_TASK (result)));
1479 *result_out = g_task_propagate_int (G_TASK (result), &error);
1480 g_assert_no_error (error);
1482 g_main_loop_quit (loop);
1486 test_object_keepalive (void)
1493 keepalive_object = object = (GObject *)g_dummy_object_new ();
1494 g_object_add_weak_pointer (object, (gpointer *)&object);
1496 task = g_task_new (object, NULL, keepalive_callback, &result);
1497 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1499 ref_count = object->ref_count;
1500 g_assert_cmpint (ref_count, >, 1);
1502 g_assert (g_task_get_source_object (task) == object);
1503 g_assert (g_async_result_get_source_object (G_ASYNC_RESULT (task)) == object);
1504 g_assert_cmpint (object->ref_count, ==, ref_count + 1);
1505 g_object_unref (object);
1507 g_object_unref (object);
1508 g_assert (object != NULL);
1510 g_task_return_int (task, magic);
1511 g_main_loop_run (loop);
1513 g_assert (object != NULL);
1514 g_assert_cmpint (result, ==, magic);
1516 g_object_unref (task);
1517 g_assert (task == NULL);
1518 g_assert (object == NULL);
1521 /* test_legacy_error: legacy GSimpleAsyncResult handling */
1522 static void test_legacy_error (void);
1525 legacy_error_callback (GObject *object,
1526 GAsyncResult *result,
1529 gssize *result_out = user_data;
1530 GError *error = NULL;
1532 g_assert (object == NULL);
1533 g_assert (g_async_result_is_tagged (result, test_legacy_error));
1534 g_assert (g_async_result_get_user_data (result) == user_data);
1536 if (g_async_result_legacy_propagate_error (result, &error))
1538 g_assert (!g_task_is_valid (result, object));
1539 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1540 g_assert (g_simple_async_result_is_valid (result, object, test_legacy_error));
1541 G_GNUC_END_IGNORE_DEPRECATIONS;
1543 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
1548 g_assert (g_task_is_valid (result, object));
1550 *result_out = g_task_propagate_int (G_TASK (result), NULL);
1551 /* Might be error, might not */
1554 g_main_loop_quit (loop);
1558 legacy_error_return (gpointer user_data)
1560 if (G_IS_TASK (user_data))
1562 GTask *task = user_data;
1564 g_task_return_int (task, magic);
1565 g_object_unref (task);
1569 GSimpleAsyncResult *simple = user_data;
1571 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1572 g_simple_async_result_set_error (simple,
1576 g_simple_async_result_complete (simple);
1577 G_GNUC_END_IGNORE_DEPRECATIONS;
1578 g_object_unref (simple);
1585 test_legacy_error (void)
1588 GSimpleAsyncResult *simple;
1592 task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1593 g_task_set_source_tag (task, test_legacy_error);
1594 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1596 g_idle_add (legacy_error_return, task);
1597 g_main_loop_run (loop);
1599 g_assert_cmpint (result, ==, magic);
1600 g_assert (task == NULL);
1603 task = g_task_new (NULL, NULL, legacy_error_callback, &result);
1604 g_task_set_source_tag (task, test_legacy_error);
1605 g_object_add_weak_pointer (G_OBJECT (task), (gpointer *)&task);
1607 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
1609 g_object_unref (task);
1610 g_main_loop_run (loop);
1612 g_assert_cmpint (result, ==, -1);
1613 g_assert (task == NULL);
1615 /* GSimpleAsyncResult error */
1616 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1617 simple = g_simple_async_result_new (NULL, legacy_error_callback, &result,
1619 G_GNUC_END_IGNORE_DEPRECATIONS;
1620 g_object_add_weak_pointer (G_OBJECT (simple), (gpointer *)&simple);
1622 g_idle_add (legacy_error_return, simple);
1623 g_main_loop_run (loop);
1625 g_assert_cmpint (result, ==, -2);
1626 g_assert (simple == NULL);
1631 main (int argc, char **argv)
1635 g_test_init (&argc, &argv, NULL);
1637 loop = g_main_loop_new (NULL, FALSE);
1638 main_thread = g_thread_self ();
1639 magic = g_get_monotonic_time ();
1641 g_test_add_func ("/gtask/basic", test_basic);
1642 g_test_add_func ("/gtask/error", test_error);
1643 g_test_add_func ("/gtask/return-from-same-iteration", test_return_from_same_iteration);
1644 g_test_add_func ("/gtask/return-from-toplevel", test_return_from_toplevel);
1645 g_test_add_func ("/gtask/return-from-anon-thread", test_return_from_anon_thread);
1646 g_test_add_func ("/gtask/return-from-wrong-thread", test_return_from_wrong_thread);
1647 g_test_add_func ("/gtask/no-callback", test_no_callback);
1648 g_test_add_func ("/gtask/report-error", test_report_error);
1649 g_test_add_func ("/gtask/priority", test_priority);
1650 g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
1651 g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
1652 g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
1653 g_test_add_func ("/gtask/run-in-thread-sync", test_run_in_thread_sync);
1654 g_test_add_func ("/gtask/run-in-thread-priority", test_run_in_thread_priority);
1655 g_test_add_func ("/gtask/return-on-cancel", test_return_on_cancel);
1656 g_test_add_func ("/gtask/return-on-cancel-sync", test_return_on_cancel_sync);
1657 g_test_add_func ("/gtask/return-on-cancel-atomic", test_return_on_cancel_atomic);
1658 g_test_add_func ("/gtask/return-pointer", test_return_pointer);
1659 g_test_add_func ("/gtask/object-keepalive", test_object_keepalive);
1660 g_test_add_func ("/gtask/legacy-error", test_legacy_error);
1664 g_main_loop_unref (loop);