[vala/staging: 3/3] codegen: Fix custom reference-counting for compact classes
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging: 3/3] codegen: Fix custom reference-counting for compact classes
- Date: Wed, 9 Oct 2019 06:10:36 +0000 (UTC)
commit f413cb32470d9c2598416772bc0166c6f974ec9f
Author: Simon Werbeck <simon werbeck gmail com>
Date: Mon Sep 30 16:37:33 2019 +0200
codegen: Fix custom reference-counting for compact classes
This fix defers emitting G_DEFINE_AUTOPTR_CLEANUP_FUNC when a compact
class defines custom unref function and set by ccode "unref_function".
codegen/valagtypemodule.vala | 40 +++++++++++++++++++++--------
tests/Makefile.am | 1 +
tests/objects/compact-class-custom-ref.vala | 29 +++++++++++++++++++++
3 files changed, 60 insertions(+), 10 deletions(-)
---
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 4eb7878a1..bae49b2c5 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -195,17 +195,21 @@ public class Vala.GTypeModule : GErrorModule {
while (base_class.base_class != null) {
base_class = base_class.base_class;
}
- string autoptr_cleanup_func;
- if (is_reference_counting (base_class)) {
- autoptr_cleanup_func = get_ccode_unref_function (base_class);
- } else {
- autoptr_cleanup_func = get_ccode_free_function (base_class);
- }
- if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") {
- Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not
available");
+ // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
+ // so we guard against that special case and handle it in generate_method_declaration.
+ if (!(base_class.is_compact && is_reference_counting (base_class))) {
+ string autoptr_cleanup_func;
+ if (is_reference_counting (base_class)) {
+ autoptr_cleanup_func = get_ccode_unref_function (base_class);
+ } else {
+ autoptr_cleanup_func = get_ccode_free_function (base_class);
+ }
+ if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") {
+ Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not
available");
+ }
+ decl_space.add_type_member_declaration (new CCodeIdentifier
("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), autoptr_cleanup_func)));
+ decl_space.add_type_member_declaration (new CCodeNewline ());
}
- decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC
(%s, %s)".printf (get_ccode_name (cl), autoptr_cleanup_func)));
- decl_space.add_type_member_declaration (new CCodeNewline ());
}
public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
@@ -441,6 +445,22 @@ public class Vala.GTypeModule : GErrorModule {
}
}
+ public override bool generate_method_declaration (Method m, CCodeFile decl_space) {
+ if (base.generate_method_declaration (m, decl_space)) {
+ // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
+ // in addition to the non-ref-countable case in generate_class_declaration.
+ unowned Class? cl = m.parent_symbol as Class;
+ if (cl != null && cl.is_compact && get_ccode_unref_function (cl) == get_ccode_name
(m)) {
+ decl_space.add_type_member_declaration (new CCodeIdentifier
("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), get_ccode_name (m))));
+ decl_space.add_type_member_declaration (new CCodeNewline ());
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct
type_struct) {
if (!m.is_abstract && !m.is_virtual) {
return;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 011fefa1a..ba8f2b0c6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -305,6 +305,7 @@ TESTS = \
objects/compact-class.vala \
objects/compact-class-destructor.vala \
objects/compact-class-refcount.vala \
+ objects/compact-class-custom-ref.vala \
objects/constructor-abstract-public.test \
objects/constructor-variadic.test \
objects/constructors.vala \
diff --git a/tests/objects/compact-class-custom-ref.vala b/tests/objects/compact-class-custom-ref.vala
new file mode 100644
index 000000000..7830665e1
--- /dev/null
+++ b/tests/objects/compact-class-custom-ref.vala
@@ -0,0 +1,29 @@
+[Compact]
+[CCode (ref_function = "foo_ref", unref_function = "foo_unref")]
+public class Foo {
+ [CCode (type = "volatile int")]
+ public int ref_count = 1;
+
+ public unowned Foo ref () {
+ AtomicInt.inc (ref ref_count);
+ return this;
+ }
+
+ public void unref () {
+ if (AtomicInt.dec_and_test (ref ref_count)) {
+ free ();
+ }
+ }
+
+ [DestroysInstance]
+ extern void free ();
+}
+
+void main () {
+ var foo = new Foo ();
+ assert(foo.ref_count == 1);
+ foo.ref ();
+ assert(foo.ref_count == 2);
+ foo.unref ();
+ assert(foo.ref_count == 1);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]