[vala] GAsync: Support async callback from closure



commit 2ae8cd1509f3489277f621440a8902b8eecf9e79
Author: Jürg Billeter <j bitron ch>
Date:   Thu Feb 4 19:02:44 2010 +0100

    GAsync: Support async callback from closure
    
    Fixes bug 608184.

 codegen/valaccodebasemodule.vala       |   15 +++++++++++++--
 codegen/valaccodedelegatemodule.vala   |    9 +++++++--
 codegen/valaccodemethodcallmodule.vala |   14 ++++++++++++--
 vala/valamemberaccess.vala             |   19 +++++++++++++++++--
 vala/valasemanticanalyzer.vala         |   17 ++++++++++++++++-
 5 files changed, 65 insertions(+), 9 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ca5af4a..7b29aed 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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 ();
diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala
index 5e4dd46..7213707 100644
--- a/codegen/valaccodedelegatemodule.vala
+++ b/codegen/valaccodedelegatemodule.vala
@@ -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 ()) {
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 5c9e3c6..f42117e 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -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) {
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 6f7f510..5e95a98 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -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) {
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index b18fe96..8d6c77f 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -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;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]