[vala/wip/queue-0.41: 12/13] codegen: Stop taking explicit references on 'this' for captured blocks
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/queue-0.41: 12/13] codegen: Stop taking explicit references on 'this' for captured blocks
- Date: Tue, 20 Mar 2018 16:42:06 +0000 (UTC)
commit be6bd02977f9552f6472728c34124530699a1d28
Author: Michal Hruby <michal mhr gmail com>
Date: Tue Mar 20 16:50:14 2018 +0100
codegen: Stop taking explicit references on 'this' for captured blocks
Use g_signal_connect_closure() and g_object_watch_closure() in GObject
environments to control their life-cycles.
https://bugzilla.gnome.org/show_bug.cgi?id=624624
codegen/valaccodebasemodule.vala | 19 +----------
codegen/valaccodemethodcallmodule.vala | 6 +---
codegen/valagsignalmodule.vala | 48 ++++++++++++++++++++++++--
tests/Makefile.am | 1 +
tests/objects/bug624624.vala | 58 ++++++++++++++++++++++++++++++++
5 files changed, 105 insertions(+), 27 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 0d4ec40..970c1d2 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2024,13 +2024,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
bool in_creation_method_with_chainup = (current_method is CreationMethod &&
current_class != null && current_class.base_class != null);
if (get_this_type () != null && (!in_creation_method_with_chainup ||
current_method.body != b)) {
- var ref_call = new CCodeFunctionCall (get_dup_func_expression
(get_data_type_for_symbol (current_type_symbol), b.source_reference));
- ref_call.add_argument (get_result_cexpression ("self"));
-
- // never increase reference count for self in finalizers to avoid
infinite recursion on following unref
- var instance = (is_in_destructor () ? (CCodeExpression) new
CCodeIdentifier ("self") : (CCodeExpression) ref_call);
-
- ccode.add_assignment (new CCodeMemberAccess.pointer
(get_variable_cexpression ("_data%d_".printf (block_id)), "self"), instance);
+ ccode.add_assignment (new CCodeMemberAccess.pointer
(get_variable_cexpression ("_data%d_".printf (block_id)), "self"), get_result_cexpression ("self"));
}
if (current_method != null) {
@@ -2214,17 +2208,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
ccode.add_expression (unref_call);
ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier
("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), new CCodeConstant ("NULL"));
- } else {
- var this_type = get_this_type ();
- if (this_type != null) {
- this_type = this_type.copy ();
- this_type.value_owned = true;
- if (this_type.is_disposable () && !is_in_destructor ()) {
- // reference count for self is not increased in finalizers
- var this_value = new GLibValue (get_data_type_for_symbol
(current_type_symbol), new CCodeIdentifier ("self"), true);
- ccode.add_expression (destroy_value (this_value));
- }
- }
}
var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 1beaa8b..6ab1597 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -315,11 +315,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall,
get_ccode_name (current_class) + "*"));
if (current_method.body.captured) {
- // capture self after setting it
- var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType
(current_class), expr.source_reference));
- ref_call.add_argument (get_this_cexpression ());
-
- ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression
("_data%d_".printf (get_block_id (current_method.body))), "self"), ref_call);
+ ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression
("_data%d_".printf (get_block_id (current_method.body))), "self"), get_this_cexpression ());
}
if (!current_class.is_compact && current_class.get_type_parameters ().size > 0) {
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index ba4b4d1..4f99941 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -623,7 +623,9 @@ public class Vala.GSignalModule : GObjectModule {
else
connect_func = get_dynamic_signal_connect_after_wrapper_name
((DynamicSignal) sig);
} else {
- if ((m != null && m.closure) || (dt != null && dt.value_owned)) {
+ if ((m != null && m.closure) && in_gobject_instance (m)) {
+ connect_func = "g_signal_connect_closure";
+ } else if ((m != null && m.closure) || (dt != null && dt.value_owned)) {
connect_func = "g_signal_connect_data";
} else if (m != null && in_gobject_instance (m)) {
connect_func = "g_signal_connect_object";
@@ -721,12 +723,41 @@ public class Vala.GSignalModule : GObjectModule {
ccall.add_argument (new CCodeConstant ("NULL"));
}
- // third resp. sixth argument: handler
- ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
+ if ((m != null && m.closure) && in_gobject_instance (m)) {
+ // g_signal_connect_closure
- if (m != null && m.closure) {
+ // third argument: closure
+ var closure_var = get_temp_variable (new CType ("GClosure*"), false, null, false);
+ var closure_ref = get_variable_cexpression (closure_var.name);
+ emit_temp_var (closure_var);
+
+ var closure_call = new CCodeFunctionCall (new CCodeIdentifier ("g_cclosure_new"));
+ // callback_func
+ closure_call.add_argument (new CCodeCastExpression (get_cvalue (handler),
"GCallback"));
+ // user_data
+ CCodeExpression handler_destroy_notify;
+ closure_call.add_argument (get_delegate_target_cexpression (handler, out
handler_destroy_notify));
+ // destroy_data
+ closure_call.add_argument (new CCodeCastExpression (handler_destroy_notify,
"GClosureNotify"));
+
+ ccode.add_assignment (closure_ref, closure_call);
+
+ var watch_call = new CCodeFunctionCall (new CCodeIdentifier
("g_object_watch_closure"));
+ watch_call.add_argument (new CCodeCastExpression (get_result_cexpression ("self"),
"GObject *"));
+ watch_call.add_argument (closure_ref);
+
+ ccode.add_expression (watch_call);
+
+ ccall.add_argument (closure_ref);
+
+ // fourth argument: after?
+ ccall.add_argument (new CCodeConstant (after ? "TRUE" : "FALSE"));
+ } else if (m != null && m.closure) {
// g_signal_connect_data
+ // third argument: handler
+ ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
+
// fourth argument: user_data
CCodeExpression handler_destroy_notify;
ccall.add_argument (get_delegate_target_cexpression (handler, out
handler_destroy_notify));
@@ -743,6 +774,9 @@ public class Vala.GSignalModule : GObjectModule {
// g_signal_connect_object or g_signal_handlers_disconnect_matched
// or dynamic_signal_connect or dynamic_signal_disconnect
+ // third resp. sixth argument: handler
+ ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
+
// fourth resp. seventh argument: object/user_data
if (handler is MemberAccess) {
var right_ma = (MemberAccess) handler;
@@ -765,6 +799,9 @@ public class Vala.GSignalModule : GObjectModule {
ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
}
} else if (dt != null && dt.delegate_symbol.has_target) {
+ // third argument: handler
+ ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
+
// fourth argument: user_data
CCodeExpression handler_destroy_notify;
ccall.add_argument (get_delegate_target_cexpression (handler, out
handler_destroy_notify));
@@ -782,6 +819,9 @@ public class Vala.GSignalModule : GObjectModule {
// g_signal_connect or g_signal_connect_after or g_signal_handlers_disconnect_matched
// or dynamic_signal_connect or dynamic_signal_disconnect
+ // third resp. sixth argument: handler
+ ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback"));
+
// fourth resp. seventh argument: user_data
ccall.add_argument (new CCodeConstant ("NULL"));
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2f3490d..4f132eb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -261,6 +261,7 @@ TESTS = \
objects/bug620675.vala \
objects/bug620706.vala \
objects/bug624594.vala \
+ objects/bug624624.vala \
objects/bug626038.vala \
objects/bug628639.vala \
objects/bug631267.vala \
diff --git a/tests/objects/bug624624.vala b/tests/objects/bug624624.vala
new file mode 100644
index 0000000..75c6a5b
--- /dev/null
+++ b/tests/objects/bug624624.vala
@@ -0,0 +1,58 @@
+class Foo : Object {
+ public static bool destroyed;
+ public signal void sig ();
+
+ ~Foo () {
+ destroyed = true;
+ }
+}
+
+class Bar : Object {
+ public static bool destroyed;
+ Foo foo;
+
+ public Bar (Foo f) {
+ foo = f;
+ foo.sig.connect (() => assert_not_reached ());
+ }
+
+ ~Bar () {
+ destroyed = true;
+ }
+}
+
+class Manam : Object {
+ public static bool destroyed;
+ public static bool reached;
+ Foo foo;
+
+ public Manam (Foo f) {
+ foo = f;
+ foo.sig.connect (() => reached = true);
+ }
+
+ ~Manam () {
+ destroyed = true;
+ }
+}
+
+void bar (Foo f) {
+ {
+ var bar = new Bar (f);
+ // bar should be finalized here
+ }
+ assert (Bar.destroyed);
+}
+
+void main () {
+ {
+ var foo = new Foo ();
+ bar (foo);
+ var manam = new Manam (foo);
+ foo.sig ();
+ assert (Manam.reached);
+ // manam and then foo should be finalized here
+ }
+ assert (Manam.destroyed);
+ assert (Foo.destroyed);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]