summaryrefslogtreecommitdiff
path: root/codegen
diff options
context:
space:
mode:
authorPrinceton Ferro <princetonferro@gmail.com>2022-01-13 02:40:18 -0500
committerRico Tzschichholz <ricotz@ubuntu.com>2022-01-17 17:33:22 +0100
commit45fe8523ad392f1aaa0f24d83b63e91774938775 (patch)
tree08b17992102f62a18712d1d563461ee481568732 /codegen
parentcd25750b52d03962220663e5c29d2a336a5fceaa (diff)
downloadvala-45fe8523ad392f1aaa0f24d83b63e91774938775.tar.gz
codegen: Add support for async main
If main() is async then setup a new GMainLoop and call _vala_main() asynchronously. Fixes https://gitlab.gnome.org/GNOME/vala/issues/1275
Diffstat (limited to 'codegen')
-rw-r--r--codegen/valaccodeattribute.vala6
-rw-r--r--codegen/valaccodemethodmodule.vala76
-rw-r--r--codegen/valagasyncmodule.vala4
3 files changed, 78 insertions, 8 deletions
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 8cf459107..bd4c6b29d 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -762,7 +762,11 @@ public class Vala.CCodeAttribute : AttributeCache {
}
if (sym.name == "main" && sym.parent_symbol.name == null) {
// avoid conflict with generated main function
- return "_vala_main";
+ if (m.coroutine) {
+ return "_vala_main_async";
+ } else {
+ return "_vala_main";
+ }
} else if (sym.name.has_prefix ("_")) {
return "_%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name.substring (1));
} else {
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index ff6d679ac..9b9fd3690 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -840,6 +840,42 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
if (m.entry_point) {
// m is possible entry point, add appropriate startup code
+
+ if (m.coroutine) {
+ // add callback for async main
+ var asyncmain_callback = new CCodeFunction (real_name + "_callback");
+ asyncmain_callback.add_parameter (new CCodeParameter ("source_object", "GObject*"));
+ asyncmain_callback.add_parameter (new CCodeParameter ("res", "GAsyncResult*"));
+ asyncmain_callback.add_parameter (new CCodeParameter ("user_data", "gpointer"));
+ asyncmain_callback.modifiers |= CCodeModifiers.STATIC;
+
+ push_function (asyncmain_callback);
+ ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", new CCodeIdentifier ("user_data")));
+
+ // get the return value
+ var finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_real_name (m)));
+ finish_call.add_argument (new CCodeIdentifier ("res"));
+ if (m.return_type is VoidType) {
+ ccode.add_expression (finish_call);
+ } else {
+ // save the return value
+ var asyncmain_result = new CCodeIdentifier (real_name + "_result");
+ var asyncmain_result_decl = new CCodeDeclaration (get_ccode_name (int_type));
+ asyncmain_result_decl.add_declarator (new CCodeVariableDeclarator (asyncmain_result.name));
+ asyncmain_result_decl.modifiers = CCodeModifiers.STATIC;
+ cfile.add_type_member_declaration (asyncmain_result_decl);
+ ccode.add_assignment (asyncmain_result, finish_call);
+ }
+
+ // quit the main loop
+ var loop_quit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_quit"));
+ loop_quit_call.add_argument (new CCodeIdentifier ("loop"));
+ ccode.add_expression (loop_quit_call);
+
+ pop_function ();
+ cfile.add_function (asyncmain_callback);
+ }
+
var cmain = new CCodeFunction ("main", "int");
cmain.line = function.line;
cmain.add_parameter (new CCodeParameter ("argc", "int"));
@@ -855,17 +891,47 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
}
}
- var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name));
+ var main_call = new CCodeFunctionCall (new CCodeIdentifier (m.coroutine ? real_name : function.name));
if (m.get_parameters ().size == 1) {
main_call.add_argument (new CCodeIdentifier ("argv"));
main_call.add_argument (new CCodeIdentifier ("argc"));
}
- if (m.return_type is VoidType) {
- // method returns void, always use 0 as exit code
+
+ if (m.coroutine) {
+ // main method is asynchronous, so we have to setup GMainLoop and run it
+ var main_loop_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_new"));
+ main_loop_new_call.add_argument (new CCodeConstantIdentifier ("NULL"));
+ main_loop_new_call.add_argument (new CCodeConstantIdentifier ("FALSE"));
+ ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", main_loop_new_call));
+
+ // add some more arguments to main_call
+ main_call.add_argument (new CCodeIdentifier (real_name + "_callback"));
+ main_call.add_argument (new CCodeIdentifier ("loop"));
ccode.add_expression (main_call);
- ccode.add_return (new CCodeConstant ("0"));
+
+ var main_loop_run_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_run"));
+ main_loop_run_call.add_argument (new CCodeIdentifier ("loop"));
+ ccode.add_expression (main_loop_run_call);
+
+ var main_loop_unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_unref"));
+ main_loop_unref_call.add_argument (new CCodeIdentifier ("loop"));
+ ccode.add_expression (main_loop_unref_call);
+
+ if (m.return_type is VoidType) {
+ // method returns void, always use 0 as exit code
+ ccode.add_return (new CCodeConstant ("0"));
+ } else {
+ // get the saved return value
+ ccode.add_return (new CCodeIdentifier (real_name + "_result"));
+ }
} else {
- ccode.add_return (main_call);
+ if (m.return_type is VoidType) {
+ // method returns void, always use 0 as exit code
+ ccode.add_expression (main_call);
+ ccode.add_return (new CCodeConstant ("0"));
+ } else {
+ ccode.add_return (main_call);
+ }
}
pop_function ();
cfile.add_function (cmain);
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index 4f130946e..bbe810496 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -354,7 +354,7 @@ public class Vala.GAsyncModule : GtkModule {
var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
- if (m.is_private_symbol ()) {
+ if (m.is_private_symbol () || m.entry_point) {
asyncfunc.modifiers |= CCodeModifiers.STATIC;
} else if (context.hide_internal && m.is_internal_symbol ()) {
asyncfunc.modifiers |= CCodeModifiers.INTERNAL;
@@ -374,7 +374,7 @@ public class Vala.GAsyncModule : GtkModule {
cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
- if (m.is_private_symbol ()) {
+ if (m.is_private_symbol () || m.entry_point) {
finishfunc.modifiers |= CCodeModifiers.STATIC;
} else if (context.hide_internal && m.is_internal_symbol ()) {
finishfunc.modifiers |= CCodeModifiers.INTERNAL;