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:
parent
781c0c3321
commit
782beb5239
@ -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 >*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user