summaryrefslogtreecommitdiff
path: root/codegen
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2016-03-23 15:04:37 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2016-11-19 12:34:31 +0100
commit14ca2e09f9021e681947fa3f1fb5c1a6974059ae (patch)
tree19eb719c3331843793308289851d1f5adfb68d81 /codegen
parenta1dd5668f7915a45e8f3c0650fa68f11d7c99730 (diff)
downloadvala-14ca2e09f9021e681947fa3f1fb5c1a6974059ae.tar.gz
codegen: Use GTask instead of GSimpleAsyncResult if 2.36 target is selected
GTask brings some differences compared to GSimpleAsyncResult. Most namely, g_task_return*() operations perform at once the async result data asignment and the caller's main context activation. This is something that has to be done exactly once, so the code flow has slight changes to ensure that. Also, the async operation data used to be attached early through g_simple_async_result_set_op_res_gpointer, only to be maybe replaced by the real return data. If GTask is being used, we set this data through g_task_set_task_data(). There's code out there relying on immediate return here when state is !=0. As GTask always defers the finalization to an idle in its main context, ensure the source is dispatched and the task completed before returning. https://bugzilla.gnome.org/show_bug.cgi?id=763345
Diffstat (limited to 'codegen')
-rw-r--r--codegen/valaccodemethodmodule.vala56
-rw-r--r--codegen/valagasyncmodule.vala161
-rw-r--r--codegen/valagdbusclientmodule.vala43
3 files changed, 202 insertions, 58 deletions
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index cee3ec18d..991b57a73 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -124,24 +124,54 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
}
public void complete_async () {
- var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_");
- var zero = new CCodeConstant ("0");
- var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero);
- ccode.open_if (state_is_zero);
-
var async_result_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_async_result");
- var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete_in_idle"));
- idle_call.add_argument (async_result_expr);
- ccode.add_expression (idle_call);
+ if (context.require_glib_version (2, 36)) {
+ var finish_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_pointer"));
+ finish_call.add_argument (async_result_expr);
+ finish_call.add_argument (new CCodeIdentifier ("_data_"));
+ finish_call.add_argument (new CCodeConstant ("NULL"));
+ ccode.add_expression (finish_call);
+
+ // Preserve the "complete now" behavior if state != 0, do so by
+ // iterating the GTask's main context till the task is complete.
+ var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_");
+ var zero = new CCodeConstant ("0");
+ var state_is_not_zero = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, state, zero);
+ ccode.open_if (state_is_not_zero);
+
+ var task_complete = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_completed"));
+ task_complete.add_argument (async_result_expr);
+ var task_is_complete = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, task_complete, new CCodeConstant ("TRUE"));
+
+ ccode.open_while (task_is_complete);
+ var task_context = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_context"));
+ task_context.add_argument (async_result_expr);
+ var iterate_context = new CCodeFunctionCall (new CCodeIdentifier ("g_main_context_iteration"));
+ iterate_context.add_argument (task_context);
+ iterate_context.add_argument (new CCodeConstant ("TRUE"));
+ ccode.add_expression (iterate_context);
+ ccode.close();
+
+ ccode.close ();
+ } else {
+ var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_");
+ var zero = new CCodeConstant ("0");
+ var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero);
+ ccode.open_if (state_is_zero);
- ccode.add_else ();
+ var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete_in_idle"));
+ idle_call.add_argument (async_result_expr);
+ ccode.add_expression (idle_call);
- var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
- direct_call.add_argument (async_result_expr);
- ccode.add_expression (direct_call);
+ ccode.add_else ();
- ccode.close ();
+ var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
+ direct_call.add_argument (async_result_expr);
+ ccode.add_expression (direct_call);
+
+ ccode.close ();
+ }
var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
unref.add_argument (async_result_expr);
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index 0ab4336d6..85d6ac5c0 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -30,7 +30,12 @@ public class Vala.GAsyncModule : GtkModule {
data.add_field ("int", "_state_");
data.add_field ("GObject*", "_source_object_");
data.add_field ("GAsyncResult*", "_res_");
- data.add_field ("GSimpleAsyncResult*", "_async_result");
+
+ if (context.require_glib_version (2, 36)) {
+ data.add_field ("GTask*", "_async_result");
+ } else {
+ data.add_field ("GSimpleAsyncResult*", "_async_result");
+ }
if (m is CreationMethod) {
data.add_field ("GType", "object_type");
@@ -207,7 +212,13 @@ public class Vala.GAsyncModule : GtkModule {
ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
ccode.add_assignment (data_var, dataalloc);
- var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
+ CCodeFunctionCall? create_result = null;
+
+ if (context.require_glib_version (2, 36)) {
+ create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
+ } else {
+ create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
+ }
var t = m.parent_symbol as TypeSymbol;
if (!(m is CreationMethod) && m.binding == MemberBinding.INSTANCE &&
@@ -220,17 +231,44 @@ public class Vala.GAsyncModule : GtkModule {
create_result.add_argument (new CCodeConstant ("NULL"));
}
+ if (context.require_glib_version (2, 36)) {
+ Parameter cancellable_param = null;
+
+ foreach (Parameter param in m.get_parameters ()) {
+ if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
+ cancellable_param = param;
+ break;
+ }
+ }
+
+ if (cancellable_param == null) {
+ create_result.add_argument (new CCodeConstant ("NULL"));
+ } else {
+ create_result.add_argument (new CCodeIdentifier (get_variable_cname (cancellable_param.name)));
+ }
+ }
+
create_result.add_argument (new CCodeIdentifier ("_callback_"));
create_result.add_argument (new CCodeIdentifier ("_user_data_"));
- create_result.add_argument (new CCodeIdentifier (get_ccode_real_name (m)));
+
+ if (!context.require_glib_version (2, 36)) {
+ create_result.add_argument (new CCodeIdentifier (get_ccode_real_name (m)));
+ }
ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result);
- var set_op_res_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
- set_op_res_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result"));
- set_op_res_call.add_argument (data_var);
- set_op_res_call.add_argument (new CCodeIdentifier (get_ccode_real_name (m) + "_data_free"));
- ccode.add_expression (set_op_res_call);
+ CCodeFunctionCall attach_data_call;
+
+ if (!context.require_glib_version (2, 36)) {
+ attach_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
+ } else {
+ attach_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_set_task_data"));
+ }
+
+ attach_data_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result"));
+ attach_data_call.add_argument (data_var);
+ attach_data_call.add_argument (new CCodeIdentifier (get_ccode_real_name (m) + "_data_free"));
+ ccode.add_expression (attach_data_call);
if (m is CreationMethod) {
ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "object_type"), new CCodeIdentifier ("object_type"));
@@ -523,23 +561,57 @@ public class Vala.GAsyncModule : GtkModule {
ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
- var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
- simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
+ if (context.require_glib_version (2, 36)) {
+ var async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_TASK"));
+ async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
- if (m.get_error_types ().size > 0) {
- // propagate error from async method
- var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error"));
- propagate_error.add_argument (simple_async_result_cast);
- propagate_error.add_argument (new CCodeIdentifier ("error"));
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer"));
+ ccall.add_argument (async_result_cast);
- ccode.open_if (propagate_error);
- return_default_value (return_type);
- ccode.close ();
- }
+ if (m.get_error_types ().size > 0) {
+ ccall.add_argument (new CCodeIdentifier ("error"));
+ } else {
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ }
+
+ ccode.add_assignment (data_var, ccall);
+
+ bool has_cancellable = false;
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
- ccall.add_argument (simple_async_result_cast);
- ccode.add_assignment (data_var, ccall);
+ foreach (Parameter param in m.get_parameters ()) {
+ if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
+ has_cancellable = true;
+ break;
+ }
+ }
+
+ // If a task is cancelled, g_task_propagate_pointer returns NULL
+ if (m.get_error_types ().size > 0 || has_cancellable) {
+ var is_null = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), data_var);
+
+ ccode.open_if (is_null);
+ return_default_value (return_type);
+ ccode.close ();
+ }
+ } else {
+ var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
+ simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
+
+ if (m.get_error_types ().size > 0) {
+ // propagate error from async method
+ var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error"));
+ propagate_error.add_argument (simple_async_result_cast);
+ propagate_error.add_argument (new CCodeIdentifier ("error"));
+
+ ccode.open_if (propagate_error);
+ return_default_value (return_type);
+ ccode.close ();
+ }
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
+ ccall.add_argument (simple_async_result_cast);
+ ccode.add_assignment (data_var, ccall);
+ }
emit_context.push_symbol (m);
foreach (Parameter param in m.get_parameters ()) {
@@ -707,18 +779,30 @@ public class Vala.GAsyncModule : GtkModule {
return;
}
- var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_from_error"));
- set_error.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_async_result"));
+ var async_result_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_async_result");
+ CCodeFunctionCall set_error = null;
+
+ if (context.require_glib_version (2, 36)) {
+ set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_error"));
+ } else {
+ set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_take_error"));
+ }
+ set_error.add_argument (async_result_expr);
set_error.add_argument (error_expr);
ccode.add_expression (set_error);
- var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
- free_error.add_argument (error_expr);
- ccode.add_expression (free_error);
-
append_local_free (current_symbol, false);
- complete_async ();
+ if (context.require_glib_version (2, 36)) {
+ // We already returned the error above, we must not return anything else here.
+ var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+ unref.add_argument (async_result_expr);
+ ccode.add_expression (unref);
+
+ ccode.add_return (new CCodeConstant ("FALSE"));
+ } else {
+ complete_async ();
+ }
}
public override void visit_return_statement (ReturnStatement stmt) {
@@ -771,17 +855,26 @@ public class Vala.GAsyncModule : GtkModule {
var res_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
res_ref.add_argument (new CCodeIdentifier ("res"));
+ CCodeFunctionCall ccall = null;
+
// store reference to async result of inner async function in out async result
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
+ if (context.require_glib_version (2, 36)) {
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_pointer"));
+ } else {
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
+ }
+
ccall.add_argument (new CCodeIdentifier ("user_data"));
ccall.add_argument (res_ref);
ccall.add_argument (new CCodeIdentifier ("g_object_unref"));
ccode.add_expression (ccall);
- // call user-provided callback
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
- ccall.add_argument (new CCodeIdentifier ("user_data"));
- ccode.add_expression (ccall);
+ if (!context.require_glib_version (2, 36)) {
+ // call user-provided callback
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
+ ccall.add_argument (new CCodeIdentifier ("user_data"));
+ ccode.add_expression (ccall);
+ }
// free async result
ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 20229fdea..00ae3ecb6 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -696,13 +696,24 @@ public class Vala.GDBusClientModule : GDBusModule {
ccall.add_argument (new CCodeConstant ("NULL"));
ccall.add_argument (cancellable);
+ CCodeFunctionCall res_wrapper = null;
+
// use wrapper as source_object wouldn't be correct otherwise
- ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
- var res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
- res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
- res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
- res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
- res_wrapper.add_argument (new CCodeConstant ("NULL"));
+ if (context.require_glib_version (2, 36)) {
+ ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
+ res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
+ res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
+ res_wrapper.add_argument (new CCodeConstant ("NULL"));
+ res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
+ res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
+ } else {
+ ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
+ res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
+ res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
+ res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
+ res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
+ res_wrapper.add_argument (new CCodeConstant ("NULL"));
+ }
ccall.add_argument (res_wrapper);
ccode.add_expression (ccall);
@@ -718,12 +729,22 @@ public class Vala.GDBusClientModule : GDBusModule {
ccall.add_argument (connection);
// unwrap async result
- var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
- inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
- ccall.add_argument (inner_res);
+ if (context.require_glib_version (2, 36)) {
+ var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer"));
+ inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GTask *"));
+ inner_res.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (inner_res);
- ccall.add_argument (new CCodeConstant ("error"));
- ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
+ ccall.add_argument (new CCodeConstant ("error"));
+ ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
+ } else {
+ var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
+ inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
+ ccall.add_argument (inner_res);
+
+ ccall.add_argument (new CCodeConstant ("error"));
+ ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
+ }
}
if (call_type == CallType.SYNC || call_type == CallType.FINISH) {