[vala] Separate async state switch from the code using goto and labels



commit af938896c1accaa88f4af8d134cdd6707631c99c
Author: Luca Bruno <lethalman88 gmail com>
Date:   Wed Mar 10 11:26:56 2010 +0100

    Separate async state switch from the code using goto and labels
    
    Fixes bug 602200.

 codegen/valaccodebasemodule.vala       |    2 ++
 codegen/valaccodemethodcallmodule.vala |    8 +++++---
 codegen/valaccodemethodmodule.vala     |   30 +++++++++++++++++++-----------
 codegen/valagasyncmodule.vala          |    5 ++++-
 4 files changed, 30 insertions(+), 15 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ea136b2..2633f8d 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -135,6 +135,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	// code nodes to be inserted before the current statement
 	// used by async method calls in coroutines
 	public CCodeFragment pre_statement_fragment;
+	// case statements to be inserted for the couroutine state
+	public CCodeSwitchStatement state_switch_statement;
 
 	/* all temporary variables */
 	public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 8439bec..9545c4e 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -715,12 +715,14 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 
 			// set state before calling async function to support immediate callbacks
 			int state = next_coroutine_state++;
-			pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
 
-			pre_statement_fragment.append (new CCodeExpressionStatement (async_call));
+			state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+			state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state)));
 
+			pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
+			pre_statement_fragment.append (new CCodeExpressionStatement (async_call));
 			pre_statement_fragment.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-			pre_statement_fragment.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+			pre_statement_fragment.append (new CCodeLabel ("_state_%d".printf (state)));
 		}
 
 		if (m is ArrayResizeMethod) {
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 39f264a..35257f1 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -268,6 +268,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		var old_temp_ref_vars = temp_ref_vars;
 		var old_variable_name_map = variable_name_map;
 		var old_try = current_try;
+		var old_state_switch_statement = state_switch_statement;
 		current_symbol = m;
 		current_method_inner_error = false;
 		next_temp_var_id = 0;
@@ -275,6 +276,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		temp_ref_vars = new ArrayList<LocalVariable> ();
 		variable_name_map = new HashMap<string,string> (str_hash, str_equal);
 		current_try = null;
+		state_switch_statement = null;
 
 		bool in_gobject_creation_method = false;
 		bool in_fundamental_creation_method = false;
@@ -292,6 +294,15 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		}
 
+		if (m.coroutine) {
+			state_switch_statement = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"));
+
+			// initial coroutine state
+			state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant ("0")));
+			state_switch_statement.add_statement (new CCodeGotoStatement ("_state_0"));
+		}
+		var current_state_switch = state_switch_statement;
+
 		var creturn_type = m.return_type;
 		if (m.return_type.is_real_non_null_struct_type ()) {
 			// structs are returned via out parameter
@@ -390,6 +401,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 		temp_ref_vars = old_temp_ref_vars;
 		variable_name_map = old_variable_name_map;
 		current_try = old_try;
+		state_switch_statement = old_state_switch_statement;
 
 		// do not declare overriding methods and interface implementations
 		if (m.is_abstract || m.is_virtual
@@ -446,23 +458,19 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 					co_function.modifiers |= CCodeModifiers.STATIC;
 					source_declarations.add_type_member_declaration (co_function.copy ());
 
-					var cswitch = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"));
-
 					// let gcc know that this can't happen
-					cswitch.add_statement (new CCodeLabel ("default"));
-					cswitch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))));
+					current_state_switch.add_statement (new CCodeLabel ("default"));
+					current_state_switch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))));
 
-					// initial coroutine state
-					cswitch.add_statement (new CCodeCaseStatement (new CCodeConstant ("0")));
+					co_function.block = new CCodeBlock ();
+					co_function.block.add_statement (current_state_switch);
 
 					// coroutine body
-					cswitch.add_statement (function.block);
+					co_function.block.add_statement (new CCodeLabel ("_state_0"));
+					co_function.block.add_statement (function.block);
 
 					// epilogue
-					cswitch.add_statement (complete_async ());
-
-					co_function.block = new CCodeBlock ();
-					co_function.block.add_statement (cswitch);
+					co_function.block.add_statement (complete_async ());
 
 					source_type_member_definition.append (co_function);
 				}
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index e6ffb0d..c9d9d76 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -519,9 +519,12 @@ internal class Vala.GAsyncModule : GSignalModule {
 
 			int state = next_coroutine_state++;
 
+			state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+			state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state)));
+
 			cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
 			cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-			cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+			cfrag.append (new CCodeLabel ("_state_%d".printf (state)));
 			cfrag.append (new CCodeEmptyStatement ());
 
 			return;



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