[vala/staging] codegen: Make every co-routine state its own CodeBlock and bump state early
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] codegen: Make every co-routine state its own CodeBlock and bump state early
- Date: Sun, 29 Oct 2017 11:57:19 +0000 (UTC)
commit 6020ae80e54c6a5cbc5d6db9bf8449b6443afa85
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Sat Oct 21 11:08:08 2017 +0200
codegen: Make every co-routine state its own CodeBlock and bump state early
https://bugzilla.gnome.org/show_bug.cgi?id=789249
ccode/valaccodefunction.vala | 13 +++++++++++++
codegen/valaccodebasemodule.vala | 4 +++-
codegen/valaccodemethodcallmodule.vala | 4 +++-
codegen/valaccodemethodmodule.vala | 1 +
codegen/valagasyncmodule.vala | 5 ++++-
codegen/valagdbusclientmodule.vala | 2 ++
tests/Makefile.am | 1 +
tests/asynchronous/bug789249.vala | 17 +++++++++++++++++
8 files changed, 44 insertions(+), 3 deletions(-)
---
diff --git a/ccode/valaccodefunction.vala b/ccode/valaccodefunction.vala
index 91addcd..7c9883d 100644
--- a/ccode/valaccodefunction.vala
+++ b/ccode/valaccodefunction.vala
@@ -314,6 +314,19 @@ public class Vala.CCodeFunction : CCodeNode {
add_statement (stmt);
}
+ public void prepend_statement (CCodeNode stmt) {
+ stmt.line = current_line;
+ current_block.prepend_statement (stmt);
+ }
+
+ public void prepend_expression (CCodeExpression expression) {
+ prepend_statement (new CCodeExpressionStatement (expression));
+ }
+
+ public void prepend_assignment (CCodeExpression left, CCodeExpression right) {
+ prepend_expression (new CCodeAssignment (left, right));
+ }
+
public void close () {
do {
var top = statement_stack.remove_at (statement_stack.size - 1);
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index cd5ae3d..ad04755 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4797,10 +4797,12 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
// set state before calling async function to support immediate callbacks
int state = emit_context.next_coroutine_state++;
- ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
+ ccode.prepend_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
ccode.add_expression (async_call);
ccode.add_return (new CCodeConstant ("FALSE"));
+
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
}
creation_expr = creation_call;
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index c911b91..10bf763 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -708,10 +708,12 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
// set state before calling async function to support immediate callbacks
int state = emit_context.next_coroutine_state++;
- ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"),
"_state_"), new CCodeConstant (state.to_string ()));
+ ccode.prepend_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
ccode.add_expression (async_call);
ccode.add_return (new CCodeConstant ("FALSE"));
+
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
}
if (expr.is_assert) {
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 4efd04b..27f8012 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -485,6 +485,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
// coroutine body
ccode.add_label ("_state_0");
+ ccode.open_block ();
}
if (m.closure) {
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index dd8e916..40157fc 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -775,11 +775,14 @@ public class Vala.GAsyncModule : GtkModule {
}
if (stmt.yield_expression == null) {
+ // set state early to support immediate callbacks
int state = emit_context.next_coroutine_state++;
- ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"),
"_state_"), new CCodeConstant (state.to_string ()));
+ ccode.prepend_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
ccode.add_return (new CCodeConstant ("FALSE"));
+
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
ccode.add_statement (new CCodeEmptyStatement ());
return;
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 4d9caa1..ef58337 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -412,7 +412,9 @@ public class Vala.GDBusClientModule : GDBusModule {
ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
ccode.add_expression (ccall);
ccode.add_return (new CCodeConstant ("FALSE"));
+
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_async_initable_new_finish"));
ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data_"), "_source_object_"));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6f18747..311eeda 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -279,6 +279,7 @@ TESTS = \
asynchronous/bug762819.vala \
asynchronous/bug777242.vala \
asynchronous/bug783543.vala \
+ asynchronous/bug789249.vala \
asynchronous/closures.vala \
asynchronous/generator.vala \
asynchronous/yield.vala \
diff --git a/tests/asynchronous/bug789249.vala b/tests/asynchronous/bug789249.vala
new file mode 100644
index 0000000..0b4bb12
--- /dev/null
+++ b/tests/asynchronous/bug789249.vala
@@ -0,0 +1,17 @@
+static int counter = 0;
+
+static async void foo () {
+ counter++;
+ assert (counter <= 1);
+
+ // This is the simplest way to trigger the issue,
+ // it may happen due to GTask/ThreadPool/threads
+ // getting to call the callback before yield, too.
+ foo.callback ();
+ yield;
+}
+
+void main () {
+ foo.begin ();
+ yield;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]