]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
GAsync: Support async callback from closure
authorJürg Billeter <j@bitron.ch>
Thu, 4 Feb 2010 18:02:44 +0000 (19:02 +0100)
committerJürg Billeter <j@bitron.ch>
Thu, 4 Feb 2010 18:02:44 +0000 (19:02 +0100)
Fixes bug 608184.

codegen/valaccodebasemodule.vala
codegen/valaccodedelegatemodule.vala
codegen/valaccodemethodcallmodule.vala
vala/valamemberaccess.vala
vala/valasemanticanalyzer.vala

index ca5af4a4ae501a61bffc047d5860e4e8a0f5c7f2..7b29aed0885a836e6622197149534c5e533eacb1 100644 (file)
@@ -1,6 +1,6 @@
 /* valaccodebasemodule.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
@@ -1802,8 +1802,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                        }
 
                        if (b.parent_symbol is Method) {
+                               var m = (Method) b.parent_symbol;
+
                                // parameters are captured with the top-level block of the method
-                               foreach (var param in ((Method) b.parent_symbol).get_parameters ()) {
+                               foreach (var param in m.get_parameters ()) {
                                        if (param.captured) {
                                                var param_type = param.parameter_type.copy ();
                                                param_type.value_owned = true;
@@ -1859,6 +1861,15 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                        }
                                }
 
+                               if (m.coroutine) {
+                                       // capture async data to allow invoking callback from inside closure
+                                       data.add_field ("gpointer", "_async_data_");
+
+                                       // async method is suspended while waiting for callback,
+                                       // so we never need to care about memory management of async data
+                                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("data"))));
+                               }
+
                                var cfrag = new CCodeFragment ();
                                append_temp_decl (cfrag, temp_vars);
                                temp_vars.clear ();
index 5e4dd46cf4af4e9b4b0330aa9d58b86665f49e3d..72137077578c989f3215385b921ebc1c28df96a6 100644 (file)
@@ -1,6 +1,6 @@
 /* valaccodedelegatemodule.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
@@ -296,7 +296,12 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (m.binding == MemberBinding.STATIC) {
                                        return new CCodeConstant ("NULL");
                                } else if (m.is_async_callback) {
-                                       return new CCodeIdentifier ("data");
+                                       if (current_method.closure) {
+                                               var block = ((Method) m.parent_symbol).body;
+                                               return new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), "_async_data_");
+                                       } else {
+                                               return new CCodeIdentifier ("data");
+                                       }
                                } else {
                                        var delegate_target = (CCodeExpression) get_ccodenode (ma.inner);
                                        if (expr_owned && ma.inner.value_type.data_type != null && ma.inner.value_type.data_type.is_reference_counting ()) {
index 5c9e3c6ea70a3fc6acb14217b1573cef95189156..f42117ee0d291c430da38ff19a8f5cfdbba68e53 100644 (file)
@@ -1,6 +1,6 @@
 /* valaccodemethodcallmodule.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
@@ -153,7 +153,17 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                }
 
                CCodeExpression instance = null;
-               if (m != null && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) {
+               if (m != null && m.is_async_callback) {
+                       if (current_method.closure) {
+                               var block = ((Method) m.parent_symbol).body;
+                               instance = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), "_async_data_");
+                       } else {
+                               instance = new CCodeIdentifier ("data");
+                       }
+
+                       in_arg_map.set (get_param_pos (m.cinstance_parameter_position), instance);
+                       out_arg_map.set (get_param_pos (m.cinstance_parameter_position), instance);
+               } else if (m != null && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) {
                        instance = (CCodeExpression) ma.inner.ccodenode;
 
                        if ((ma.member_name == "begin" || ma.member_name == "end") && ma.inner.symbol_reference == ma.symbol_reference) {
index 6f7f51034f95491d106c64d9cf69cbab0b2efa49..5e95a98cafb0343f53430180b42cdd08195413e7 100644 (file)
@@ -1,6 +1,6 @@
 /* valamemberaccess.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -471,7 +471,22 @@ public class Vala.MemberAccess : Expression {
                        var m = (Method) member;
                        if (m.is_async_callback) {
                                // ensure to use right callback method for virtual/abstract async methods
-                               m = analyzer.current_method.get_callback_method ();
+                               // and also for lambda expressions within async methods
+                               var async_method = analyzer.current_async_method;
+
+                               if (async_method != analyzer.current_method) {
+                                       Symbol sym = analyzer.current_method;
+                                       while (sym != async_method) {
+                                               var method = sym as Method;
+                                               if (method != null) {
+                                                       method.closure = true;
+                                               }
+                                               sym = sym.parent_symbol;
+                                       }
+                                       async_method.body.captured = true;
+                               }
+
+                               m = async_method.get_callback_method ();
                                symbol_reference = m;
                                member = symbol_reference;
                        } else if (m.base_method != null) {
index b18fe9663b33239905e7b394edeb4797962411a8..8d6c77f4f2dc543f65024c69e82fea2a2dd5d39f 100644 (file)
@@ -1,6 +1,6 @@
 /* valasemanticanalyzer.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
@@ -66,6 +66,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
+       public Method? current_async_method {
+               get {
+                       var sym = current_symbol;
+                       while (sym is Block || sym is Method) {
+                               var m = sym as Method;
+                               if (m != null && m.coroutine) {
+                                       break;
+                               }
+
+                               sym = sym.parent_symbol;
+                       }
+                       return sym as Method;
+               }
+       }
+
        public PropertyAccessor? current_property_accessor {
                get {
                        var sym = current_symbol;