[vala] Fix memory leak with owned property getters and g_object_get
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Fix memory leak with owned property getters and g_object_get
- Date: Sun, 21 Mar 2010 18:05:35 +0000 (UTC)
commit 8974eb665656a24a8efee29f963a84c82ecbac44
Author: Jürg Billeter <j bitron ch>
Date: Sun Mar 21 19:03:52 2010 +0100
Fix memory leak with owned property getters and g_object_get
Fixes bug 576152.
codegen/valaccodebasemodule.vala | 12 +++++
codegen/valaccodemodule.vala | 4 ++
codegen/valagobjectmodule.vala | 6 ++-
codegen/valagtypemodule.vala | 83 ++++++++++++++++++++++++++++++++++++++
vala/valaclass.vala | 20 +++++++++
vala/valatypesymbol.vala | 12 +++++-
vapi/glib-2.0.vapi | 2 +-
vapi/gobject-2.0.vapi | 6 +-
8 files changed, 138 insertions(+), 7 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ded33db..d25ba87 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -478,6 +478,18 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
+ public override CCodeIdentifier get_value_taker_function (DataType type_reference) {
+ var array_type = type_reference as ArrayType;
+ if (type_reference.data_type != null) {
+ return new CCodeIdentifier (type_reference.data_type.get_take_value_function ());
+ } else if (array_type != null && array_type.element_type.data_type == string_type.data_type) {
+ // G_TYPE_STRV
+ return new CCodeIdentifier ("g_value_take_boxed");
+ } else {
+ return new CCodeIdentifier ("g_value_set_pointer");
+ }
+ }
+
CCodeIdentifier get_value_getter_function (DataType type_reference) {
var array_type = type_reference as ArrayType;
if (type_reference.data_type != null) {
diff --git a/codegen/valaccodemodule.vala b/codegen/valaccodemodule.vala
index 939c49f..d8e88e3 100644
--- a/codegen/valaccodemodule.vala
+++ b/codegen/valaccodemodule.vala
@@ -351,6 +351,10 @@ public abstract class Vala.CCodeModule {
return next.get_value_setter_function (type_reference);
}
+ public virtual CCodeIdentifier get_value_taker_function (DataType type_reference) {
+ return next.get_value_taker_function (type_reference);
+ }
+
public virtual CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) {
return next.get_construct_property_assignment (canonical_cconstant, property_type, value);
}
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index 6290a68..bf5c94d 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -243,7 +243,11 @@ internal class Vala.GObjectModule : GTypeModule {
ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (prefix, prop.name)));
ccall.add_argument (cself);
var csetcall = new CCodeFunctionCall ();
- csetcall.call = head.get_value_setter_function (prop.property_type);
+ if (prop.get_accessor.value_type.value_owned) {
+ csetcall.call = head.get_value_taker_function (prop.property_type);
+ } else {
+ csetcall.call = head.get_value_setter_function (prop.property_type);
+ }
csetcall.add_argument (new CCodeIdentifier ("value"));
csetcall.add_argument (ccall);
cswitch.add_statement (new CCodeExpressionStatement (csetcall));
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 7f6de7e..7353e66 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -136,6 +136,18 @@ internal class Vala.GTypeModule : GErrorModule {
decl_space.add_type_member_declaration (function);
+ function = new CCodeFunction (cl.get_take_value_function (), "void");
+ function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
+ function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
+
+ if (cl.access == SymbolAccessibility.PRIVATE) {
+ function.modifiers = CCodeModifiers.STATIC;
+ // avoid C warning as this function is not always used
+ function.attributes = "G_GNUC_UNUSED";
+ }
+
+ decl_space.add_type_member_declaration (function);
+
function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
@@ -537,6 +549,7 @@ internal class Vala.GTypeModule : GErrorModule {
add_g_param_spec_type_function (cl);
add_g_value_get_function (cl);
add_g_value_set_function (cl);
+ add_g_value_take_function (cl);
var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
@@ -994,6 +1007,76 @@ internal class Vala.GTypeModule : GErrorModule {
source_type_member_definition.append (function);
}
+ private void add_g_value_take_function (Class cl) {
+ var function = new CCodeFunction (cl.get_take_value_function (), "void");
+ function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
+ function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
+
+ if (cl.access == SymbolAccessibility.PRIVATE) {
+ function.modifiers = CCodeModifiers.STATIC;
+ }
+
+ var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
+
+ var init_block = new CCodeBlock ();
+ function.block = init_block;
+
+ var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*");
+ ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old"));
+ init_block.add_statement (ctypedecl);
+
+ var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
+ ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
+ ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+ ccall.add_argument (ccall_typecheck);
+ init_block.add_statement (new CCodeExpressionStatement (ccall));
+
+ init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE)));
+
+ var true_stmt = new CCodeBlock ();
+ var false_stmt = new CCodeBlock ();
+ var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt);
+ init_block.add_statement (if_statement);
+
+
+ ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
+ ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
+ ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+ ccall.add_argument (ccall_typecheck);
+ true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+
+ var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
+ ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
+
+ var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
+ ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
+
+ var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
+ ccall_typecompatible.add_argument (ccall_typefrominstance);
+ ccall_typecompatible.add_argument (ccall_gvaluetype);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+ ccall.add_argument (ccall_typecompatible);
+ true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+
+ true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE)));
+
+ false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
+
+ true_stmt = new CCodeBlock ();
+ if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt);
+ init_block.add_statement (if_statement);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
+ ccall.add_argument (new CCodeIdentifier ("old"));
+ true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+ source_type_member_definition.append (function);
+ }
+
private void add_g_value_get_function (Class cl) {
var function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 4fc73a2..eceedf3 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -123,6 +123,7 @@ public class Vala.Class : ObjectTypeSymbol {
private string marshaller_type_name;
private string get_value_function;
private string set_value_function;
+ private string take_value_function;
private bool _is_compact;
private bool _is_immutable;
@@ -633,6 +634,9 @@ public class Vala.Class : ObjectTypeSymbol {
if (a.has_argument ("set_value_function")) {
set_value_function = a.get_string ("set_value_function");
}
+ if (a.has_argument ("take_value_function")) {
+ take_value_function = a.get_string ("take_value_function");
+ }
if (a.has_argument ("const_cname")) {
const_cname = a.get_string ("const_cname");
@@ -755,6 +759,22 @@ public class Vala.Class : ObjectTypeSymbol {
return set_value_function;
}
+ public override string? get_take_value_function () {
+ if (take_value_function == null) {
+ if (is_fundamental ()) {
+ take_value_function = get_lower_case_cname ("value_take_");
+ } else if (base_class != null) {
+ take_value_function = base_class.get_take_value_function ();
+ } else if (get_type_id () == "G_TYPE_POINTER") {
+ take_value_function = "g_value_set_pointer";
+ } else {
+ take_value_function = "g_value_take_boxed";
+ }
+ }
+
+ return take_value_function;
+ }
+
public override bool is_reference_counting () {
return get_ref_function () != null;
}
diff --git a/vala/valatypesymbol.vala b/vala/valatypesymbol.vala
index 7be7b97..996e5dc 100644
--- a/vala/valatypesymbol.vala
+++ b/vala/valatypesymbol.vala
@@ -1,6 +1,7 @@
/* valatypesymbol.vala
*
- * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2010 Jürg Billeter
+ * Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -195,7 +196,14 @@ public abstract class Vala.TypeSymbol : Symbol {
public virtual string? get_set_value_function () {
return null;
}
-
+
+ /**
+ * Returns the cname of the GValue taker function.
+ */
+ public virtual string? get_take_value_function () {
+ return null;
+ }
+
/**
* Returns the C name of this data type in upper case. Words are
* separated by underscores. The upper case C name of the namespace is
diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi
index e6d2e34..18872b0 100644
--- a/vapi/glib-2.0.vapi
+++ b/vapi/glib-2.0.vapi
@@ -818,7 +818,7 @@ public enum NormalizeMode {
[Compact]
[Immutable]
-[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", type_signature = "s")]
+[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", take_value_function = "g_value_take_string", type_signature = "s")]
public class string {
[CCode (cname = "strstr")]
public unowned string? str (string needle);
diff --git a/vapi/gobject-2.0.vapi b/vapi/gobject-2.0.vapi
index ec9378a..2f08988 100644
--- a/vapi/gobject-2.0.vapi
+++ b/vapi/gobject-2.0.vapi
@@ -109,7 +109,7 @@ namespace GLib {
public virtual void unload ();
}
- [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param")]
+ [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param", take_value_function = "g_value_take_param")]
public class ParamSpec {
public string name;
public ParamFlags flags;
@@ -288,7 +288,7 @@ namespace GLib {
[CCode (instance_pos = 0)]
public delegate void WeakNotify (Object object);
- [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")]
+ [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", take_value_function = "g_value_take_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")]
public class Object {
public uint ref_count;
@@ -401,7 +401,7 @@ namespace GLib {
[CCode (has_target = false)]
public delegate void ValueTransform (Value src_value, out Value dest_value);
- [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", type_signature = "v")]
+ [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", take_value_function = "g_value_take_boxed", type_signature = "v")]
public struct Value {
[CCode (cname = "G_VALUE_HOLDS")]
public bool holds (Type type);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]