We already have two ways of creating a QOM object with a parent set
from birth: object_initialize_child() for objects embedded in the
parent struct, and object_new_with_props() for heap-allocated objects
that also want a list of string properties applied.  What we do not
have is the plain heap-allocated dual of object_initialize_child():
create the object, add it as a child<> of a given parent under a given
name, and hand the reference to the parent.

Board and composite-device code that heap-allocates children today
therefore either open-codes object_new()+object_property_add_child()
+object_unref(), or skips the parenting step entirely and lets
device_set_realized() dump the object into /machine/unattached.

Add object_new_child(parent, id, typename) as that missing primitive.
The reference created by object_new() is transferred to the parent's
child<> property, so on return the sole reference is held by @parent
and the caller does not need to unref.  Later patches build the qdev
and per-bus creation helpers on top of this.

@id must be a valid QOM child<> property name: non-empty and
without the "/" QOM path separator.  It may contain the "[*]"
auto-index suffix; the qdev id_wellformed() grammar does not apply
here.  The compiler enforces non-NULL arguments via
__attribute__((nonnull)) instead of runtime asserts, as suggested by
Richard and Peter.

Link: https://lore.kernel.org/qemu-devel/[email protected]/
Suggested-by: Markus Armbruster <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
AI-used-for: code (refactoring)
Signed-off-by: Alexander Graf <[email protected]>
---
 include/qom/object.h | 32 ++++++++++++++++++++++++++++++++
 qom/object.c         | 12 ++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/include/qom/object.h b/include/qom/object.h
index 11f55613fc..299673d040 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -632,6 +632,38 @@ Object *object_new_with_class(ObjectClass *klass);
  */
 Object *object_new(const char *typename);
 
+/**
+ * object_new_child:
+ * @parent: the QOM composition-tree parent
+ * @id: the child<> property name; the object's canonical QOM path
+ *      becomes @parent's path plus "/" plus @id
+ * @typename: the name of the type of the object to instantiate
+ *
+ * Create a heap-allocated object and immediately add it to the QOM
+ * composition tree as a child of @parent.
+ *
+ * This is the heap-allocated dual of object_initialize_child(): use
+ * this when the child is a pointer member of the parent, and use
+ * object_initialize_child() when the child is embedded in the parent
+ * struct.  See also object_new_with_props() for the variant that
+ * additionally sets a list of properties.
+ *
+ * The reference returned by object_new() is transferred to the child<>
+ * property of @parent, so the object has a reference count of 1 held
+ * by @parent, and the caller does not need to unref.
+ *
+ * The @id assert is a sanity check on the caller's string literal;
+ * the authoritative uniqueness check is object_property_add_child(),
+ * which will error_abort() on a duplicate @id under @parent.  Use
+ * the "[*]" auto-index suffix when multiple children of the same
+ * kind may be created.
+ *
+ * Returns: the newly allocated, instantiated and parented object.
+ */
+Object *object_new_child(Object *parent, const char *id,
+                         const char *typename)
+    __attribute__((nonnull(1, 2, 3), returns_nonnull));
+
 /**
  * object_new_with_props:
  * @typename:  The name of the type of the object to instantiate.
diff --git a/qom/object.c b/qom/object.c
index f79b2cf361..64b0faf1f5 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -718,6 +718,18 @@ Object *object_new(const char *typename)
     return object_new_with_type(ti);
 }
 
+Object *object_new_child(Object *parent, const char *id,
+                         const char *typename)
+{
+    Object *obj;
+
+    g_assert(id[0] && !strchr(id, '/'));
+
+    obj = object_new(typename);
+    object_property_add_child(parent, id, obj);
+    object_unref(obj);
+    return obj;
+}
 
 Object *object_new_with_props(const char *typename,
                               Object *parent,
-- 
2.47.1


Reply via email to