* [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts
@ 2013-01-17 7:31 Andreas Färber
2013-01-17 16:48 ` Eduardo Habkost
2013-01-20 20:53 ` Anthony Liguori
0 siblings, 2 replies; 4+ messages in thread
From: Andreas Färber @ 2013-01-17 7:31 UTC (permalink / raw)
To: qemu-devel; +Cc: ehabkost, anthony, Andreas Färber
Add a documentation section "Methods" and discuss among others how to
handle overriding virtual methods.
Clarify DeviceClass::realize documentation and refer to the above.
Signed-off-by: Andreas Färber <afaerber@suse.de>
---
hw/qdev-core.h | 14 +++++--
include/qom/object.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--
2 Dateien geändert, 111 Zeilen hinzugefügt(+), 7 Zeilen entfernt(-)
diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 3d75ae2..731aadd 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -60,14 +60,20 @@ struct VMStateDescription;
* The @init callback is considered private to a particular bus implementation
* (immediate abstract child types of TYPE_DEVICE). Derived leaf types set an
* "init" callback on their parent class instead.
+ *
* Any type may override the @realize and/or @unrealize callbacks but needs
- * to call (and thus save) the parent type's implementation if so desired.
- * Usually this means storing the previous value of, e.g., @realized inside
- * the type's class structure and overwriting it with a function that first
- * invokes the stored callback, then performs any additional steps.
+ * to call the parent type's implementation if keeping their functionality
+ * is desired. Refer to QOM documentation for further discussion and examples.
+ *
+ * <note>
+ * <para>
* If a type derived directly from TYPE_DEVICE implements @realize, it does
* not need to implement @init and therefore does not need to store and call
* #DeviceClass' default @realize callback.
+ * For other types consult the documentation and implementation of the
+ * respective parent types.
+ * </para>
+ * </note>
*/
typedef struct DeviceClass {
/*< private >*/
diff --git a/include/qom/object.h b/include/qom/object.h
index 1ef2f0e..8e16ea8 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -147,9 +147,9 @@ typedef struct InterfaceInfo InterfaceInfo;
* </programlisting>
* </example>
*
- * Introducing new virtual functions requires a class to define its own
- * struct and to add a .class_size member to the TypeInfo. Each function
- * will also have a wrapper to call it easily:
+ * Introducing new virtual methods requires a class to define its own
+ * struct and to add a .class_size member to the #TypeInfo. Each method
+ * will also have a wrapper function to call it easily:
*
* <example>
* <title>Defining an abstract class</title>
@@ -186,6 +186,104 @@ typedef struct InterfaceInfo InterfaceInfo;
* similar to normal types except for the fact that are only defined by
* their classes and never carry any state. You can dynamically cast an object
* to one of its #Interface types and vice versa.
+ *
+ * # Methods #
+ *
+ * A <emphasis>method</emphasis> is a function within the namespace scope of
+ * a class. It usually operates on the object instance by passing it as a
+ * strongly-typed first argument.
+ * If it does not operate on an object instance, it is dubbed
+ * <emphasis>class method</emphasis>.
+ *
+ * Methods cannot be overloaded. That is, the #ObjectClass and method name
+ * uniquely identity the function to be called; the signature does not vary
+ * except for trailing varargs.
+ *
+ * Methods are always <emphasis>virtual</emphasis>. Overriding a method in
+ * #TypeInfo.class_init of a subclass leads to any user of the class obtained
+ * via OBJECT_GET_CLASS() accessing the overridden function.
+ * The original function is not automatically invoked. It is the responsability
+ * of the overriding class to determine whether and when to invoke the method
+ * being overridden.
+ *
+ * To invoke the method being overridden, the preferred solution is to store
+ * the original value in the overriding class before overriding the method.
+ * This corresponds to |[ {super,base}.method(...) ]| in Java and C#
+ * respectively; this frees the overriding class from hardcoding its parent
+ * class, which someone might choose to change at some point.
+ *
+ * <example>
+ * <title>Overriding a virtual method</title>
+ * <programlisting>
+ * typedef struct MyState MyState;
+ *
+ * typedef void (*MyDoSomething)(MyState *obj);
+ *
+ * typedef struct MyClass {
+ * ObjectClass parent_class;
+ *
+ * MyDoSomething do_something;
+ * } MyClass;
+ *
+ * static void my_do_something(MyState *obj)
+ * {
+ * // do something
+ * }
+ *
+ * static void my_class_init(ObjectClass *oc, void *data)
+ * {
+ * MyClass *mc = MY_CLASS(oc);
+ *
+ * mc->do_something = my_do_something;
+ * }
+ *
+ * static const TypeInfo my_type_info = {
+ * .name = TYPE_MY,
+ * .parent = TYPE_OBJECT,
+ * .instance_size = sizeof(MyState),
+ * .class_size = sizeof(MyClass),
+ * .class_init = my_class_init,
+ * };
+ *
+ * typedef struct DerivedClass {
+ * MyClass parent_class;
+ *
+ * MyDoSomething parent_do_something;
+ * } MyClass;
+ *
+ * static void derived_do_something(MyState *obj)
+ * {
+ * DerivedClass *dc = DERIVED_GET_CLASS(obj);
+ *
+ * // do something here
+ * dc->parent_do_something(obj);
+ * // do something else here
+ * }
+ *
+ * static void derived_class_init(ObjectClass *oc, void *data)
+ * {
+ * MyClass *mc = MY_CLASS(oc);
+ * DerivedClass *dc = DERIVED_CLASS(oc);
+ *
+ * dc->parent_do_something = mc->do_something;
+ * mc->do_something = derived_do_something;
+ * }
+ *
+ * static const TypeInfo derived_type_info = {
+ * .name = TYPE_DERIVED,
+ * .parent = TYPE_MY,
+ * .class_size = sizeof(DerivedClass),
+ * .class_init = my_class_init,
+ * };
+ * </programlisting>
+ * </example>
+ *
+ * Alternatively, object_class_by_name() can be used to obtain the class and
+ * its non-overridden methods for a specific type. This would correspond to
+ * |[ MyClass::method(...) ]| in C++.
+ *
+ * The first example of such a QOM method was #CPUClass.reset,
+ * another example is #DeviceClass.realize.
*/
--
1.7.10.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts
2013-01-17 7:31 [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts Andreas Färber
@ 2013-01-17 16:48 ` Eduardo Habkost
2013-01-17 18:55 ` Anthony Liguori
2013-01-20 20:53 ` Anthony Liguori
1 sibling, 1 reply; 4+ messages in thread
From: Eduardo Habkost @ 2013-01-17 16:48 UTC (permalink / raw)
To: Andreas Färber; +Cc: qemu-devel, anthony
On Thu, Jan 17, 2013 at 08:31:50AM +0100, Andreas Färber wrote:
> Add a documentation section "Methods" and discuss among others how to
> handle overriding virtual methods.
>
> Clarify DeviceClass::realize documentation and refer to the above.
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
> hw/qdev-core.h | 14 +++++--
> include/qom/object.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 Dateien geändert, 111 Zeilen hinzugefügt(+), 7 Zeilen entfernt(-)
>
> diff --git a/hw/qdev-core.h b/hw/qdev-core.h
> index 3d75ae2..731aadd 100644
> --- a/hw/qdev-core.h
> +++ b/hw/qdev-core.h
> @@ -60,14 +60,20 @@ struct VMStateDescription;
> * The @init callback is considered private to a particular bus implementation
> * (immediate abstract child types of TYPE_DEVICE). Derived leaf types set an
> * "init" callback on their parent class instead.
> + *
> * Any type may override the @realize and/or @unrealize callbacks but needs
> - * to call (and thus save) the parent type's implementation if so desired.
> - * Usually this means storing the previous value of, e.g., @realized inside
> - * the type's class structure and overwriting it with a function that first
> - * invokes the stored callback, then performs any additional steps.
> + * to call the parent type's implementation if keeping their functionality
> + * is desired. Refer to QOM documentation for further discussion and examples.
> + *
> + * <note>
> + * <para>
> * If a type derived directly from TYPE_DEVICE implements @realize, it does
> * not need to implement @init and therefore does not need to store and call
> * #DeviceClass' default @realize callback.
> + * For other types consult the documentation and implementation of the
> + * respective parent types.
> + * </para>
> + * </note>
The above looks clearer to me, thanks!
But I still have a question about the preferred method to make
subclasses call the parent implementation, below:
> */
> typedef struct DeviceClass {
> /*< private >*/
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 1ef2f0e..8e16ea8 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -147,9 +147,9 @@ typedef struct InterfaceInfo InterfaceInfo;
> * </programlisting>
> * </example>
> *
> - * Introducing new virtual functions requires a class to define its own
> - * struct and to add a .class_size member to the TypeInfo. Each function
> - * will also have a wrapper to call it easily:
> + * Introducing new virtual methods requires a class to define its own
> + * struct and to add a .class_size member to the #TypeInfo. Each method
> + * will also have a wrapper function to call it easily:
> *
> * <example>
> * <title>Defining an abstract class</title>
> @@ -186,6 +186,104 @@ typedef struct InterfaceInfo InterfaceInfo;
> * similar to normal types except for the fact that are only defined by
> * their classes and never carry any state. You can dynamically cast an object
> * to one of its #Interface types and vice versa.
> + *
> + * # Methods #
> + *
> + * A <emphasis>method</emphasis> is a function within the namespace scope of
> + * a class. It usually operates on the object instance by passing it as a
> + * strongly-typed first argument.
> + * If it does not operate on an object instance, it is dubbed
> + * <emphasis>class method</emphasis>.
> + *
> + * Methods cannot be overloaded. That is, the #ObjectClass and method name
> + * uniquely identity the function to be called; the signature does not vary
> + * except for trailing varargs.
> + *
> + * Methods are always <emphasis>virtual</emphasis>. Overriding a method in
> + * #TypeInfo.class_init of a subclass leads to any user of the class obtained
> + * via OBJECT_GET_CLASS() accessing the overridden function.
> + * The original function is not automatically invoked. It is the responsability
> + * of the overriding class to determine whether and when to invoke the method
> + * being overridden.
> + *
> + * To invoke the method being overridden, the preferred solution is to store
> + * the original value in the overriding class before overriding the method.
> + * This corresponds to |[ {super,base}.method(...) ]| in Java and C#
> + * respectively; this frees the overriding class from hardcoding its parent
> + * class, which someone might choose to change at some point.
> + *
> + * <example>
> + * <title>Overriding a virtual method</title>
> + * <programlisting>
> + * typedef struct MyState MyState;
> + *
> + * typedef void (*MyDoSomething)(MyState *obj);
> + *
> + * typedef struct MyClass {
> + * ObjectClass parent_class;
> + *
> + * MyDoSomething do_something;
> + * } MyClass;
> + *
> + * static void my_do_something(MyState *obj)
> + * {
> + * // do something
> + * }
> + *
> + * static void my_class_init(ObjectClass *oc, void *data)
> + * {
> + * MyClass *mc = MY_CLASS(oc);
> + *
> + * mc->do_something = my_do_something;
> + * }
> + *
> + * static const TypeInfo my_type_info = {
> + * .name = TYPE_MY,
> + * .parent = TYPE_OBJECT,
> + * .instance_size = sizeof(MyState),
> + * .class_size = sizeof(MyClass),
> + * .class_init = my_class_init,
> + * };
> + *
> + * typedef struct DerivedClass {
> + * MyClass parent_class;
> + *
> + * MyDoSomething parent_do_something;
> + * } MyClass;
> + *
> + * static void derived_do_something(MyState *obj)
> + * {
> + * DerivedClass *dc = DERIVED_GET_CLASS(obj);
> + *
> + * // do something here
> + * dc->parent_do_something(obj);
> + * // do something else here
> + * }
> + *
> + * static void derived_class_init(ObjectClass *oc, void *data)
> + * {
> + * MyClass *mc = MY_CLASS(oc);
> + * DerivedClass *dc = DERIVED_CLASS(oc);
> + *
> + * dc->parent_do_something = mc->do_something;
> + * mc->do_something = derived_do_something;
> + * }
> + *
> + * static const TypeInfo derived_type_info = {
> + * .name = TYPE_DERIVED,
> + * .parent = TYPE_MY,
> + * .class_size = sizeof(DerivedClass),
> + * .class_init = my_class_init,
> + * };
> + * </programlisting>
> + * </example>
> + *
> + * Alternatively, object_class_by_name() can be used to obtain the class and
> + * its non-overridden methods for a specific type. This would correspond to
> + * |[ MyClass::method(...) ]| in C++.
I still wonder why resolving/saving/calling thie parent class method at
runtime (using any of the two methods described above) is better than
simply making the corresponding parent_class_method() function public,
so it can be called directly by classes that override the method.
Is there any use-case where resolving the parent class implementation at
runtime is really necessary?
> + *
> + * The first example of such a QOM method was #CPUClass.reset,
> + * another example is #DeviceClass.realize.
> */
>
>
> --
> 1.7.10.4
>
--
Eduardo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts
2013-01-17 16:48 ` Eduardo Habkost
@ 2013-01-17 18:55 ` Anthony Liguori
0 siblings, 0 replies; 4+ messages in thread
From: Anthony Liguori @ 2013-01-17 18:55 UTC (permalink / raw)
To: Eduardo Habkost, Andreas Färber; +Cc: qemu-devel
Eduardo Habkost <ehabkost@redhat.com> writes:
> On Thu, Jan 17, 2013 at 08:31:50AM +0100, Andreas Färber wrote:
>> + * Alternatively, object_class_by_name() can be used to obtain the class and
>> + * its non-overridden methods for a specific type. This would correspond to
>> + * |[ MyClass::method(...) ]| in C++.
>
> I still wonder why resolving/saving/calling thie parent class method at
> runtime (using any of the two methods described above) is better than
> simply making the corresponding parent_class_method() function public,
> so it can be called directly by classes that override the method.
It's idiomatic from GObject.
I'm not sure I can come up with a concrete example but in the absense of
a compelling reason to shift from the idiom, I'd strongly suggest not.
Regards,
Anthony Liguori
>
> Is there any use-case where resolving the parent class implementation at
> runtime is really necessary?
>
>
>> + *
>> + * The first example of such a QOM method was #CPUClass.reset,
>> + * another example is #DeviceClass.realize.
>> */
>>
>>
>> --
>> 1.7.10.4
>>
>
> --
> Eduardo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts
2013-01-17 7:31 [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts Andreas Färber
2013-01-17 16:48 ` Eduardo Habkost
@ 2013-01-20 20:53 ` Anthony Liguori
1 sibling, 0 replies; 4+ messages in thread
From: Anthony Liguori @ 2013-01-20 20:53 UTC (permalink / raw)
To: None, qemu-devel; +Cc: ehabkost, anthony
Applied. Thanks.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-01-20 20:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-17 7:31 [Qemu-devel] [PATCH for-1.4] qom: Extend documentation on QOM method concepts Andreas Färber
2013-01-17 16:48 ` Eduardo Habkost
2013-01-17 18:55 ` Anthony Liguori
2013-01-20 20:53 ` Anthony Liguori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).