From: Valeri Ochinski Date: Sun, 17 Dec 2023 15:33:18 +0000 (+0300) Subject: codegen: Use GWeakRef for [SingleInstance] constructors X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0723d0fb91edc1298dcb79d9653e0276209197ae;p=thirdparty%2Fvala.git codegen: Use GWeakRef for [SingleInstance] constructors This prevents a potential race condition if object is destroyed at the same time as it is created, since lock is not taken by the code removing a weak reference. GWeakRef gives atomicity guarantees. --- diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala index e2179f1f4..0cd60344c 100644 --- a/codegen/valagobjectmodule.vala +++ b/codegen/valagobjectmodule.vala @@ -524,8 +524,8 @@ public class Vala.GObjectModule : GTypeModule { var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl)); var singleton_once_name = "%s_singleton__once".printf (get_ccode_name (cl)); - var singleton_ref = new CCodeDeclaration("GObject *"); - singleton_ref.add_declarator (new CCodeVariableDeclarator (singleton_ref_name, new CCodeConstant ("NULL"))); + var singleton_ref = new CCodeDeclaration("GWeakRef"); + singleton_ref.add_declarator (new CCodeVariableDeclarator (singleton_ref_name)); singleton_ref.modifiers = CCodeModifiers.STATIC; ccode.add_statement (singleton_ref); @@ -564,17 +564,17 @@ public class Vala.GObjectModule : GTypeModule { singleton_mutex_lock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); ccode.add_statement (new CCodeExpressionStatement (singleton_mutex_lock)); - var check_existance = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (singleton_ref_name), new CCodeConstant ("NULL")); - var return_singleton = new CCodeBlock(); + var get_from_singleton = new CCodeFunctionCall (new CCodeIdentifier ("g_weak_ref_get")); + get_from_singleton.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name))); + ccode.add_assignment (new CCodeIdentifier ("obj"), get_from_singleton); - var ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref")); - ref_object.add_argument (new CCodeIdentifier (singleton_ref_name)); - return_singleton.add_statement (new CCodeExpressionStatement (ref_object)); + var check_existance = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("obj"), new CCodeConstant ("NULL")); + var return_singleton = new CCodeBlock(); var singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock")); singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); return_singleton.add_statement (new CCodeExpressionStatement (singleton_mutex_unlock)); - return_singleton.add_statement (new CCodeReturnStatement (new CCodeIdentifier (singleton_ref_name))); + return_singleton.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj"))); var if_singleton_alive = new CCodeIfStatement (check_existance, return_singleton); ccode.add_statement (if_singleton_alive); @@ -609,12 +609,10 @@ public class Vala.GObjectModule : GTypeModule { var singleton_ref_name = "%s_singleton__ref".printf (get_ccode_name (cl)); var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl)); - ccode.add_assignment (new CCodeIdentifier (singleton_ref_name), new CCodeIdentifier ("obj")); - - var set_weak_ref_to_volatile = new CCodeFunctionCall (new CCodeIdentifier ("g_object_add_weak_pointer")); - set_weak_ref_to_volatile.add_argument (new CCodeIdentifier (singleton_ref_name)); - set_weak_ref_to_volatile.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name)), "gpointer")); - ccode.add_statement (new CCodeExpressionStatement (set_weak_ref_to_volatile)); + var set_singleton_reference = new CCodeFunctionCall (new CCodeIdentifier ("g_weak_ref_set")); + set_singleton_reference.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name))); + set_singleton_reference.add_argument (new CCodeIdentifier ("obj")); + ccode.add_statement (new CCodeExpressionStatement (set_singleton_reference)); var final_singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock")); final_singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); diff --git a/tests/objects/singleton.c-expected b/tests/objects/singleton.c-expected index 5a5887b88..b08773c34 100644 --- a/tests/objects/singleton.c-expected +++ b/tests/objects/singleton.c-expected @@ -118,7 +118,7 @@ foo_constructor (GType type, { GObject * obj; GObjectClass * parent_class; - static GObject * Foo_singleton__ref = NULL; + static GWeakRef Foo_singleton__ref; static GMutex Foo_singleton__lock; static volatile gsize Foo_singleton__once = 0; Foo * self; @@ -127,16 +127,15 @@ foo_constructor (GType type, g_once_init_leave (&Foo_singleton__once, 42); } g_mutex_lock (&Foo_singleton__lock); - if (Foo_singleton__ref != NULL) { - g_object_ref (Foo_singleton__ref); + obj = g_weak_ref_get (&Foo_singleton__ref); + if (obj != NULL) { g_mutex_unlock (&Foo_singleton__lock); - return Foo_singleton__ref; + return obj; } parent_class = G_OBJECT_CLASS (foo_parent_class); obj = parent_class->constructor (type, n_construct_properties, construct_properties); self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_FOO, Foo); - Foo_singleton__ref = obj; - g_object_add_weak_pointer (Foo_singleton__ref, (gpointer) (&Foo_singleton__ref)); + g_weak_ref_set (&Foo_singleton__ref, obj); g_mutex_unlock (&Foo_singleton__lock); return obj; } @@ -207,7 +206,7 @@ bar_constructor (GType type, { GObject * obj; GObjectClass * parent_class; - static GObject * Bar_singleton__ref = NULL; + static GWeakRef Bar_singleton__ref; static GMutex Bar_singleton__lock; static volatile gsize Bar_singleton__once = 0; Bar * self; @@ -216,16 +215,15 @@ bar_constructor (GType type, g_once_init_leave (&Bar_singleton__once, 42); } g_mutex_lock (&Bar_singleton__lock); - if (Bar_singleton__ref != NULL) { - g_object_ref (Bar_singleton__ref); + obj = g_weak_ref_get (&Bar_singleton__ref); + if (obj != NULL) { g_mutex_unlock (&Bar_singleton__lock); - return Bar_singleton__ref; + return obj; } parent_class = G_OBJECT_CLASS (bar_parent_class); obj = parent_class->constructor (type, n_construct_properties, construct_properties); self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_BAR, Bar); - Bar_singleton__ref = obj; - g_object_add_weak_pointer (Bar_singleton__ref, (gpointer) (&Bar_singleton__ref)); + g_weak_ref_set (&Bar_singleton__ref, obj); g_mutex_unlock (&Bar_singleton__lock); return obj; }