qom: Extend documentation on QOM method concepts

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>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Andreas Färber 2013-01-17 08:31:50 +01:00 committed by Anthony Liguori
parent 781c0c3321
commit 782beb5239
2 changed files with 111 additions and 7 deletions

View File

@ -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 >*/

View File

@ -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.
*/