add_statement (stmt);
}
- public void close () {
+ 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 (CCodeBlock? block = null) {
+ //FIXME Don't ignore this invalid close without further action
+ if (block != null && statement_stack.index_of (block) >= 0) {
+ return;
+ }
+
do {
var top = statement_stack.remove_at (statement_stack.size - 1);
current_block = top as CCodeBlock;
+ if (current_block == block) {
+ current_block = null;
+ }
} while (current_block == null);
}
}
public Map<string,int> closure_variable_count_map = new HashMap<string,int> (str_hash, str_equal);
public Map<LocalVariable,int> closure_variable_clash_map = new HashMap<LocalVariable,int> ();
public bool is_in_method_precondition;
+ public CCodeBlock? current_co_state_block;
public EmitContext (Symbol? symbol = null) {
current_symbol = symbol;
// 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"));
+
+ if (state > 0) {
+ ccode.close (emit_context.current_co_state_block);
+ emit_context.current_co_state_block = null;
+ }
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
+ emit_context.current_co_state_block = ccode.current_block;
}
creation_expr = creation_call;
// set state before calling async function to support immediate callbacks
int state = emit_context.next_coroutine_state++;
- ccode.add_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ()));
+ ccode.prepend_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ()));
ccode.add_expression (async_call);
ccode.add_return (new CCodeConstant ("FALSE"));
+
+ if (state > 0) {
+ ccode.close (emit_context.current_co_state_block);
+ emit_context.current_co_state_block = null;
+ }
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
+ emit_context.current_co_state_block = ccode.current_block;
}
if (expr.is_assert) {
// coroutine body
ccode.add_label ("_state_0");
+ ccode.open_block ();
+ emit_context.current_co_state_block = ccode.current_block;
}
if (m.closure) {
return;
}
+ // 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"));
+
+ if (state > 0) {
+ ccode.close (emit_context.current_co_state_block);
+ emit_context.current_co_state_block = null;
+ }
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
+ emit_context.current_co_state_block = ccode.current_block;
ccode.add_statement (new CCodeEmptyStatement ());
}
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"));
+ if (state > 0) {
+ ccode.close (emit_context.current_co_state_block);
+ emit_context.current_co_state_block = null;
+ }
ccode.add_label ("_state_%d".printf (state));
+ ccode.open_block ();
+ emit_context.current_co_state_block = ccode.current_block;
ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
ccall.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"), "GAsyncInitable *"));
asynchronous/bug762819.vala \
asynchronous/bug777242.vala \
asynchronous/bug783543.vala \
+ asynchronous/bug789249.vala \
asynchronous/bug792660.vala \
asynchronous/bug792942.vala \
asynchronous/bug793158.vala \
--- /dev/null
+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 ();
+}