Patchwork [1/9] qom: add qom_init_completion

login
register
mail settings
Submitter Michael Roth
Date May 3, 2013, 4:03 p.m.
Message ID <1367597032-28934-2-git-send-email-mdroth@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/241338/
State New
Headers show

Comments

Michael Roth - May 3, 2013, 4:03 p.m.
This is similar in concept to "realize", though semantics are a
bit more open-ended:

And object might in some cases need a number of properties to be
specified before it can be "used"/"started"/etc. This can't always
be done via an open-ended new() function, the main example being objects
that around created via the command-line by -object.

To support these cases we allow a function, ->instance_init_completion,
to be registered that will be called by the -object constructor, or can
be called at the end of new() constructors and such.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 include/qom/object.h |   19 +++++++++++++++++++
 qom/object.c         |   21 +++++++++++++++++++++
 vl.c                 |    2 ++
 3 files changed, 42 insertions(+)
Paolo Bonzini - May 6, 2013, 7:45 a.m.
Il 03/05/2013 18:03, Michael Roth ha scritto:
> This is similar in concept to "realize", though semantics are a
> bit more open-ended:
> 
> And object might in some cases need a number of properties to be
> specified before it can be "used"/"started"/etc. This can't always
> be done via an open-ended new() function, the main example being objects
> that around created via the command-line by -object.
> 
> To support these cases we allow a function, ->instance_init_completion,
> to be registered that will be called by the -object constructor, or can
> be called at the end of new() constructors and such.

This seems a lot like a realize property that cannot be set back to false...

Paolo

> Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
> ---
>  include/qom/object.h |   19 +++++++++++++++++++
>  qom/object.c         |   21 +++++++++++++++++++++
>  vl.c                 |    2 ++
>  3 files changed, 42 insertions(+)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index d0f99c5..86f1e2e 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -394,6 +394,11 @@ struct Object
>   * @instance_init: This function is called to initialize an object.  The parent
>   *   class will have already been initialized so the type is only responsible
>   *   for initializing its own members.
> + * @instance_init_completion: This function is used mainly cases where an
> + *   object has been instantiated via the command-line, and is called once all
> + *   properties specified via command-line have been set for the object. This
> + *   is not called automatically, but manually via @object_init_completion once
> + *   the processing of said properties is completed.
>   * @instance_finalize: This function is called during object destruction.  This
>   *   is called before the parent @instance_finalize function has been called.
>   *   An object should only free the members that are unique to its type in this
> @@ -429,6 +434,7 @@ struct TypeInfo
>  
>      size_t instance_size;
>      void (*instance_init)(Object *obj);
> +    void (*instance_init_completion)(Object *obj);
>      void (*instance_finalize)(Object *obj);
>  
>      bool abstract;
> @@ -562,6 +568,19 @@ struct InterfaceClass
>  Object *object_new(const char *typename);
>  
>  /**
> + * object_init_completion:
> + * @obj: The object to complete initialization of
> + *
> + * In cases where an object is instantiated from a command-line with a number
> + * of properties specified as parameters (generally via -object), or for cases
> + * where a new()/helper function is used to pass/set some minimal number of
> + * properties that are required prior to completion of object initialization,
> + * this function can be called to mark when that occurs to complete object
> + * initialization.
> + */
> +void object_init_completion(Object *obj);
> +
> +/**
>   * object_new_with_type:
>   * @type: The type of the object to instantiate.
>   *
> diff --git a/qom/object.c b/qom/object.c
> index 75e6aac..c932f64 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -50,6 +50,7 @@ struct TypeImpl
>      void *class_data;
>  
>      void (*instance_init)(Object *obj);
> +    void (*instance_init_completion)(Object *obj);
>      void (*instance_finalize)(Object *obj);
>  
>      bool abstract;
> @@ -110,6 +111,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
>      ti->class_data = info->class_data;
>  
>      ti->instance_init = info->instance_init;
> +    ti->instance_init_completion = info->instance_init_completion;
>      ti->instance_finalize = info->instance_finalize;
>  
>      ti->abstract = info->abstract;
> @@ -422,6 +424,25 @@ Object *object_new(const char *typename)
>      return object_new_with_type(ti);
>  }
>  
> +
> +static void object_init_completion_with_type(Object *obj, TypeImpl *ti)
> +{
> +    if (type_has_parent(ti)) {
> +        object_init_completion_with_type(obj, type_get_parent(ti));
> +    }
> +
> +    if (ti->instance_init_completion) {
> +        ti->instance_init_completion(obj);
> +    }
> +}
> +
> +void object_init_completion(Object *obj)
> +{
> +    TypeImpl *ti = type_get_by_name(object_get_class(obj)->type->name);
> +
> +    object_init_completion_with_type(obj, ti);
> +}
> +
>  Object *object_dynamic_cast(Object *obj, const char *typename)
>  {
>      if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
> diff --git a/vl.c b/vl.c
> index 6e6225f..d454c86 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2831,6 +2831,8 @@ static int object_create(QemuOpts *opts, void *opaque)
>      object_property_add_child(container_get(object_get_root(), "/objects"),
>                                id, obj, NULL);
>  
> +    object_init_completion(obj);
> +
>      return 0;
>  }
>  
>
Michael Roth - May 6, 2013, 7:01 p.m.
On Mon, May 06, 2013 at 09:45:22AM +0200, Paolo Bonzini wrote:
> Il 03/05/2013 18:03, Michael Roth ha scritto:
> > This is similar in concept to "realize", though semantics are a
> > bit more open-ended:
> > 
> > And object might in some cases need a number of properties to be
> > specified before it can be "used"/"started"/etc. This can't always
> > be done via an open-ended new() function, the main example being objects
> > that around created via the command-line by -object.
> > 
> > To support these cases we allow a function, ->instance_init_completion,
> > to be registered that will be called by the -object constructor, or can
> > be called at the end of new() constructors and such.
> 
> This seems a lot like a realize property that cannot be set back to false...

I seem to recall some other conditions like properties not being
modifiable after being realized? In this case though I think event loops
should be startable/stoppable via properties (post-migration, for
instance, or maybe testing/debugging) with simple qom-set commands.

Not too sure honestly, mainly I just recalled realize() being pushed
down into DeviceState for specific reasons, and didn't want to confuse
this with being the same thing (even though it does seem very similar).
I'm not sure what the best approach is here.

> 
> Paolo
> 
> > Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
> > ---
> >  include/qom/object.h |   19 +++++++++++++++++++
> >  qom/object.c         |   21 +++++++++++++++++++++
> >  vl.c                 |    2 ++
> >  3 files changed, 42 insertions(+)
> > 
> > diff --git a/include/qom/object.h b/include/qom/object.h
> > index d0f99c5..86f1e2e 100644
> > --- a/include/qom/object.h
> > +++ b/include/qom/object.h
> > @@ -394,6 +394,11 @@ struct Object
> >   * @instance_init: This function is called to initialize an object.  The parent
> >   *   class will have already been initialized so the type is only responsible
> >   *   for initializing its own members.
> > + * @instance_init_completion: This function is used mainly cases where an
> > + *   object has been instantiated via the command-line, and is called once all
> > + *   properties specified via command-line have been set for the object. This
> > + *   is not called automatically, but manually via @object_init_completion once
> > + *   the processing of said properties is completed.
> >   * @instance_finalize: This function is called during object destruction.  This
> >   *   is called before the parent @instance_finalize function has been called.
> >   *   An object should only free the members that are unique to its type in this
> > @@ -429,6 +434,7 @@ struct TypeInfo
> >  
> >      size_t instance_size;
> >      void (*instance_init)(Object *obj);
> > +    void (*instance_init_completion)(Object *obj);
> >      void (*instance_finalize)(Object *obj);
> >  
> >      bool abstract;
> > @@ -562,6 +568,19 @@ struct InterfaceClass
> >  Object *object_new(const char *typename);
> >  
> >  /**
> > + * object_init_completion:
> > + * @obj: The object to complete initialization of
> > + *
> > + * In cases where an object is instantiated from a command-line with a number
> > + * of properties specified as parameters (generally via -object), or for cases
> > + * where a new()/helper function is used to pass/set some minimal number of
> > + * properties that are required prior to completion of object initialization,
> > + * this function can be called to mark when that occurs to complete object
> > + * initialization.
> > + */
> > +void object_init_completion(Object *obj);
> > +
> > +/**
> >   * object_new_with_type:
> >   * @type: The type of the object to instantiate.
> >   *
> > diff --git a/qom/object.c b/qom/object.c
> > index 75e6aac..c932f64 100644
> > --- a/qom/object.c
> > +++ b/qom/object.c
> > @@ -50,6 +50,7 @@ struct TypeImpl
> >      void *class_data;
> >  
> >      void (*instance_init)(Object *obj);
> > +    void (*instance_init_completion)(Object *obj);
> >      void (*instance_finalize)(Object *obj);
> >  
> >      bool abstract;
> > @@ -110,6 +111,7 @@ static TypeImpl *type_register_internal(const TypeInfo *info)
> >      ti->class_data = info->class_data;
> >  
> >      ti->instance_init = info->instance_init;
> > +    ti->instance_init_completion = info->instance_init_completion;
> >      ti->instance_finalize = info->instance_finalize;
> >  
> >      ti->abstract = info->abstract;
> > @@ -422,6 +424,25 @@ Object *object_new(const char *typename)
> >      return object_new_with_type(ti);
> >  }
> >  
> > +
> > +static void object_init_completion_with_type(Object *obj, TypeImpl *ti)
> > +{
> > +    if (type_has_parent(ti)) {
> > +        object_init_completion_with_type(obj, type_get_parent(ti));
> > +    }
> > +
> > +    if (ti->instance_init_completion) {
> > +        ti->instance_init_completion(obj);
> > +    }
> > +}
> > +
> > +void object_init_completion(Object *obj)
> > +{
> > +    TypeImpl *ti = type_get_by_name(object_get_class(obj)->type->name);
> > +
> > +    object_init_completion_with_type(obj, ti);
> > +}
> > +
> >  Object *object_dynamic_cast(Object *obj, const char *typename)
> >  {
> >      if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
> > diff --git a/vl.c b/vl.c
> > index 6e6225f..d454c86 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -2831,6 +2831,8 @@ static int object_create(QemuOpts *opts, void *opaque)
> >      object_property_add_child(container_get(object_get_root(), "/objects"),
> >                                id, obj, NULL);
> >  
> > +    object_init_completion(obj);
> > +
> >      return 0;
> >  }
> >  
> > 
>

Patch

diff --git a/include/qom/object.h b/include/qom/object.h
index d0f99c5..86f1e2e 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -394,6 +394,11 @@  struct Object
  * @instance_init: This function is called to initialize an object.  The parent
  *   class will have already been initialized so the type is only responsible
  *   for initializing its own members.
+ * @instance_init_completion: This function is used mainly cases where an
+ *   object has been instantiated via the command-line, and is called once all
+ *   properties specified via command-line have been set for the object. This
+ *   is not called automatically, but manually via @object_init_completion once
+ *   the processing of said properties is completed.
  * @instance_finalize: This function is called during object destruction.  This
  *   is called before the parent @instance_finalize function has been called.
  *   An object should only free the members that are unique to its type in this
@@ -429,6 +434,7 @@  struct TypeInfo
 
     size_t instance_size;
     void (*instance_init)(Object *obj);
+    void (*instance_init_completion)(Object *obj);
     void (*instance_finalize)(Object *obj);
 
     bool abstract;
@@ -562,6 +568,19 @@  struct InterfaceClass
 Object *object_new(const char *typename);
 
 /**
+ * object_init_completion:
+ * @obj: The object to complete initialization of
+ *
+ * In cases where an object is instantiated from a command-line with a number
+ * of properties specified as parameters (generally via -object), or for cases
+ * where a new()/helper function is used to pass/set some minimal number of
+ * properties that are required prior to completion of object initialization,
+ * this function can be called to mark when that occurs to complete object
+ * initialization.
+ */
+void object_init_completion(Object *obj);
+
+/**
  * object_new_with_type:
  * @type: The type of the object to instantiate.
  *
diff --git a/qom/object.c b/qom/object.c
index 75e6aac..c932f64 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -50,6 +50,7 @@  struct TypeImpl
     void *class_data;
 
     void (*instance_init)(Object *obj);
+    void (*instance_init_completion)(Object *obj);
     void (*instance_finalize)(Object *obj);
 
     bool abstract;
@@ -110,6 +111,7 @@  static TypeImpl *type_register_internal(const TypeInfo *info)
     ti->class_data = info->class_data;
 
     ti->instance_init = info->instance_init;
+    ti->instance_init_completion = info->instance_init_completion;
     ti->instance_finalize = info->instance_finalize;
 
     ti->abstract = info->abstract;
@@ -422,6 +424,25 @@  Object *object_new(const char *typename)
     return object_new_with_type(ti);
 }
 
+
+static void object_init_completion_with_type(Object *obj, TypeImpl *ti)
+{
+    if (type_has_parent(ti)) {
+        object_init_completion_with_type(obj, type_get_parent(ti));
+    }
+
+    if (ti->instance_init_completion) {
+        ti->instance_init_completion(obj);
+    }
+}
+
+void object_init_completion(Object *obj)
+{
+    TypeImpl *ti = type_get_by_name(object_get_class(obj)->type->name);
+
+    object_init_completion_with_type(obj, ti);
+}
+
 Object *object_dynamic_cast(Object *obj, const char *typename)
 {
     if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
diff --git a/vl.c b/vl.c
index 6e6225f..d454c86 100644
--- a/vl.c
+++ b/vl.c
@@ -2831,6 +2831,8 @@  static int object_create(QemuOpts *opts, void *opaque)
     object_property_add_child(container_get(object_get_root(), "/objects"),
                               id, obj, NULL);
 
+    object_init_completion(obj);
+
     return 0;
 }