]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Use GWeakRef for [SingleInstance] constructors
authorValeri Ochinski <v19930312@gmail.com>
Sun, 17 Dec 2023 15:33:18 +0000 (18:33 +0300)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 18 Dec 2023 19:36:40 +0000 (20:36 +0100)
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.

codegen/valagobjectmodule.vala
tests/objects/singleton.c-expected

index e2179f1f49ddfa1b1686120ccbfc5b7378ec6d0d..0cd60344cb2dafdf278a579c7c8a09d5113f5fd4 100644 (file)
@@ -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)));
index 5a5887b8861d4ba8b26c10a859d6b1ca7c21c388..b08773c34c1ad6229b6b994634ab6bb3d715e9ea 100644 (file)
@@ -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;
 }