]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Make the task_complete flag for < 2.44 more similar to >= 2.44 be27b9e6d1b7cb590dcda6be6621d707887c87cb
authorCarlos Garnacho <carlosg@gnome.org>
Mon, 12 Jun 2017 15:19:05 +0000 (17:19 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 12 Jun 2017 17:13:15 +0000 (19:13 +0200)
According to the g_task_get_completed() docs (which we rely on for
glib >= 2.44 targets): "This changes from FALSE to TRUE after the task's
callback is invoked, and will return FALSE from inside the callback".

So to make the code paths most similar to >= 2.44 (when
g_task_get_completed is available), wrap the GAsyncReadyCallback with
one of our own, that just invokes the nested callback (if any) and turns
on the flag.

Also remove the code turning on the flag on finish(), it's superfluous
now and there are no guarantees that it will be invoked.

https://bugzilla.gnome.org/show_bug.cgi?id=783543

codegen/valagasyncmodule.vala
tests/Makefile.am
tests/asynchronous/bug783543.vala [new file with mode: 0644]

index 002c488ca69c0444f9834d0d12088b051230bb63..dd8e916e202bdaea8596d5310e6a10a53bd85ff4 100644 (file)
@@ -33,6 +33,7 @@ public class Vala.GAsyncModule : GtkModule {
 
                data.add_field ("GTask*", "_async_result");
                if (!context.require_glib_version (2, 44)) {
+                       data.add_field ("GAsyncReadyCallback", "_callback_");
                        data.add_field ("gboolean", "_task_complete_");
                }
 
@@ -160,9 +161,58 @@ public class Vala.GAsyncModule : GtkModule {
                return freefunc;
        }
 
+       void generate_async_ready_callback_wrapper (Method m, string function_name) {
+               var function = new CCodeFunction (function_name, "void");
+               function.modifiers = CCodeModifiers.STATIC;
+
+               function.add_parameter (new CCodeParameter ("*source_object", "GObject"));
+               function.add_parameter (new CCodeParameter ("*res", "GAsyncResult"));
+               function.add_parameter (new CCodeParameter ("*user_data", "void"));
+
+               push_function (function);
+
+               // Set _task_complete_ to false after calling back to the real func
+               var async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_TASK"));
+               async_result_cast.add_argument (new CCodeIdentifier ("res"));
+
+               var dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data";
+               ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_task_data_"));
+
+               var get_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_task_data"));
+               get_data_call.add_argument (async_result_cast);
+
+               var data_var = new CCodeIdentifier ("_task_data_");
+               ccode.add_assignment (data_var, get_data_call);
+
+               var task_inner_callback = new CCodeMemberAccess.pointer (data_var, "_callback_");
+               var callback_is_nonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, task_inner_callback, new CCodeConstant ("NULL"));
+
+               ccode.open_if (callback_is_nonnull);
+               var nested_callback = new CCodeFunctionCall (task_inner_callback);
+               nested_callback.add_argument (new CCodeIdentifier ("source_object"));
+               nested_callback.add_argument (new CCodeIdentifier ("res"));
+               nested_callback.add_argument (new CCodeIdentifier ("user_data"));
+               ccode.add_expression (nested_callback);
+               ccode.close ();
+
+               ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_task_complete_"), new CCodeConstant ("TRUE"));
+
+               pop_function ();
+
+               cfile.add_function_declaration (function);
+               cfile.add_function (function);
+       }
+
        void generate_async_function (Method m) {
                push_context (new EmitContext ());
 
+               string? callback_wrapper = null;
+
+               if (!context.require_glib_version (2, 44)) {
+                       callback_wrapper = get_ccode_real_name (m) + "_async_ready_wrapper";
+                       generate_async_ready_callback_wrapper (m, callback_wrapper);
+               }
+
                var dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data";
                var asyncfunc = new CCodeFunction (get_ccode_real_name (m), "void");
                var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
@@ -211,6 +261,10 @@ public class Vala.GAsyncModule : GtkModule {
                ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
                ccode.add_assignment (data_var, dataalloc);
 
+               if (!context.require_glib_version (2, 44)) {
+                       ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_callback_"), new CCodeConstant ("_callback_"));
+               }
+
                var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
 
                var t = m.parent_symbol as TypeSymbol;
@@ -239,7 +293,11 @@ public class Vala.GAsyncModule : GtkModule {
                        create_result.add_argument (new CCodeIdentifier (get_variable_cname (cancellable_param.name)));
                }
 
-               create_result.add_argument (new CCodeIdentifier ("_callback_"));
+               if (context.require_glib_version (2, 44)) {
+                       create_result.add_argument (new CCodeIdentifier ("_callback_"));
+               } else {
+                       create_result.add_argument (new CCodeIdentifier (callback_wrapper));
+               }
                create_result.add_argument (new CCodeIdentifier ("_user_data_"));
 
                ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result);
@@ -584,11 +642,6 @@ public class Vala.GAsyncModule : GtkModule {
                        ccode.close ();
                }
 
-               if (!context.require_glib_version (2, 44)) {
-                       var task_completed_var = new CCodeMemberAccess.pointer (data_var, "_task_complete_");
-                       ccode.add_assignment (task_completed_var, new CCodeConstant ("TRUE"));
-               }
-
                emit_context.push_symbol (m);
                foreach (Parameter param in m.get_parameters ()) {
                        if (param.direction != ParameterDirection.IN) {
index 765d26b13b2850570c0a678b3e823b34b7588fd1..061184922481ae7cf1ff83ccc6206c902d8cded1 100644 (file)
@@ -266,6 +266,7 @@ TESTS = \
        asynchronous/bug742621.vala \
        asynchronous/bug762819.vala \
        asynchronous/bug777242.vala \
+       asynchronous/bug783543.vala \
        asynchronous/closures.vala \
        asynchronous/generator.vala \
        asynchronous/yield.vala \
diff --git a/tests/asynchronous/bug783543.vala b/tests/asynchronous/bug783543.vala
new file mode 100644 (file)
index 0000000..08148f4
--- /dev/null
@@ -0,0 +1,15 @@
+class Foo : Object {
+       public async void bar () {
+               Idle.add (bar.callback);
+               yield;
+       }
+}
+
+void main () {
+       var loop = new MainLoop ();
+       var foo = new Foo ();
+       foo.bar.begin (() => {
+               loop.quit ();
+       });
+       loop.run ();
+}