--- Makefile.objs | 2 +- hw/object.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/object.h | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/qdev.h | 7 + hw/qobject.c | 463 -------------------------------------------------------- hw/qobject.h | 471 --------------------------------------------------------- 6 files changed, 942 insertions(+), 935 deletions(-) create mode 100644 hw/object.c create mode 100644 hw/object.h delete mode 100644 hw/qobject.c delete mode 100644 hw/qobject.h
diff --git a/Makefile.objs b/Makefile.objs index 8e629f1..c77c0af 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -123,7 +123,7 @@ common-obj-$(CONFIG_WIN32) += version.o common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o -common-obj-y += qobject.o +common-obj-y += object.o audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o audio-obj-$(CONFIG_SDL) += sdlaudio.o diff --git a/hw/object.c b/hw/object.c new file mode 100644 index 0000000..be61677 --- /dev/null +++ b/hw/object.c @@ -0,0 +1,463 @@ +/* + * QEMU Object Model + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aligu...@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "object.h" + +#define MAX_INTERFACES 32 + +typedef struct InterfaceImpl +{ + const char *parent; + void (*interface_initfn)(ObjectClass *class); + Type type; +} InterfaceImpl; + +typedef struct TypeImpl +{ + const char *name; + Type type; + + size_t class_size; + + size_t instance_size; + + void (*base_init)(ObjectClass *klass); + void (*base_finalize)(ObjectClass *klass); + + void (*class_init)(ObjectClass *klass); + void (*class_finalize)(ObjectClass *klass); + + void (*instance_init)(Object *obj); + void (*instance_finalize)(Object *obj); + + bool abstract; + + const char *parent; + + ObjectClass *class; + + int num_interfaces; + InterfaceImpl interfaces[MAX_INTERFACES]; +} TypeImpl; + +static int num_types = 1; +static TypeImpl type_table[1024]; + +Type type_register_static(const TypeInfo *info) +{ + Type type = num_types++; + TypeImpl *ti; + + ti = &type_table[type]; + + assert(info->name != NULL); + + ti->name = info->name; + ti->parent = info->parent; + ti->type = type; + + ti->class_size = info->class_size; + ti->instance_size = info->instance_size; + + ti->base_init = info->base_init; + ti->base_finalize = info->base_finalize; + + ti->class_init = info->class_init; + ti->class_finalize = info->class_finalize; + + ti->instance_init = info->instance_init; + ti->instance_finalize = info->instance_finalize; + + ti->abstract = info->abstract; + + if (info->interfaces) { + int i; + + for (i = 0; info->interfaces[i].type; i++) { + ti->interfaces[i].parent = info->interfaces[i].type; + ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; + ti->num_interfaces++; + } + } + + return type; +} + +static Type type_register_anonymous(const TypeInfo *info) +{ + Type type = num_types++; + TypeImpl *ti; + char buffer[32]; + static int count; + + ti = &type_table[type]; + + snprintf(buffer, sizeof(buffer), "<anonymous-%d>", count++); + ti->name = g_strdup(buffer); + ti->parent = g_strdup(info->parent); + ti->type = type; + + ti->class_size = info->class_size; + ti->instance_size = info->instance_size; + + ti->base_init = info->base_init; + ti->base_finalize = info->base_finalize; + + ti->class_init = info->class_init; + ti->class_finalize = info->class_finalize; + + ti->instance_init = info->instance_init; + ti->instance_finalize = info->instance_finalize; + + if (info->interfaces) { + int i; + + for (i = 0; info->interfaces[i].type; i++) { + ti->interfaces[i].parent = info->interfaces[i].type; + ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; + ti->num_interfaces++; + } + } + + return type; +} + +static TypeImpl *type_get_instance(Type type) +{ + assert(type != 0); + assert(type < num_types); + + return &type_table[type]; +} + +Type type_get_by_name(const char *name) +{ + int i; + + if (name == NULL) { + return 0; + } + + for (i = 1; i < num_types; i++) { + if (strcmp(name, type_table[i].name) == 0) { + return i; + } + } + + return 0; +} + +static void type_class_base_init(TypeImpl *base_ti, const char *typename) +{ + TypeImpl *ti; + + if (!typename) { + return; + } + + ti = type_get_instance(type_get_by_name(typename)); + + type_class_base_init(base_ti, ti->parent); + + if (ti->base_init) { + ti->base_init(base_ti->class); + } +} + +static size_t type_class_get_size(TypeImpl *ti) +{ + if (ti->class_size) { + return ti->class_size; + } + + if (ti->parent) { + return type_class_get_size(type_get_instance(type_get_by_name(ti->parent))); + } + + return sizeof(ObjectClass); +} + +static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) +{ + TypeInfo info = { + .instance_size = sizeof(Interface), + .parent = iface->parent, + .class_size = sizeof(InterfaceClass), + .class_init = iface->interface_initfn, + .abstract = true, + }; + + iface->type = type_register_anonymous(&info); +} + +static void type_class_init(TypeImpl *ti) +{ + size_t class_size = sizeof(ObjectClass); + int i; + + if (ti->class) { + return; + } + + ti->class_size = type_class_get_size(ti); + + ti->class = g_malloc0(ti->class_size); + ti->class->type = ti->type; + + if (ti->parent) { + TypeImpl *ti_parent; + + ti_parent = type_get_instance(type_get_by_name(ti->parent)); + + type_class_init(ti_parent); + + class_size = ti_parent->class_size; + assert(ti_parent->class_size <= ti->class_size); + + memcpy((void *)ti->class + sizeof(ObjectClass), + (void *)ti_parent->class + sizeof(ObjectClass), + ti_parent->class_size - sizeof(ObjectClass)); + } + + memset((void *)ti->class + class_size, 0, ti->class_size - class_size); + + type_class_base_init(ti, ti->parent); + + for (i = 0; i < ti->num_interfaces; i++) { + type_class_interface_init(ti, &ti->interfaces[i]); + } + + if (ti->class_init) { + ti->class_init(ti->class); + } +} + +static void object_interface_init(Object *obj, InterfaceImpl *iface) +{ + TypeImpl *ti = type_get_instance(iface->type); + Interface *iface_obj; + + iface_obj = INTERFACE(object_new(ti->name)); + iface_obj->obj = obj; + + obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); +} + +static void object_init(Object *obj, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + int i; + + if (ti->parent) { + object_init(obj, ti->parent); + } + + for (i = 0; i < ti->num_interfaces; i++) { + object_interface_init(obj, &ti->interfaces[i]); + } + + if (ti->instance_init) { + ti->instance_init(obj); + } +} + +void object_initialize(void *data, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + Object *obj = data; + + g_assert(ti->instance_size >= sizeof(ObjectClass)); + + type_class_init(ti); + + g_assert(ti->abstract == false); + + memset(obj, 0, ti->instance_size); + + obj->class = ti->class; + + object_init(obj, typename); +} + +static void object_deinit(Object *obj, const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + + if (ti->instance_finalize) { + ti->instance_finalize(obj); + } + + while (obj->interfaces) { + Interface *iface_obj = obj->interfaces->data; + obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); + object_delete(OBJECT(iface_obj)); + } + + if (ti->parent) { + object_init(obj, ti->parent); + } +} + +void object_finalize(void *data) +{ + Object *obj = data; + TypeImpl *ti = type_get_instance(obj->class->type); + + object_deinit(obj, ti->name); +} + +const char *type_get_name(Type type) +{ + TypeImpl *ti = type_get_instance(type); + return ti->name; +} + +Object *object_new(const char *typename) +{ + TypeImpl *ti = type_get_instance(type_get_by_name(typename)); + Object *obj; + + obj = g_malloc(ti->instance_size); + object_initialize(obj, typename); + + return obj; +} + +void object_delete(Object *obj) +{ + object_finalize(obj); + g_free(obj); +} + +bool object_is_type(Object *obj, const char *typename) +{ + Type target_type = type_get_by_name(typename); + Type type = obj->class->type; + GSList *i; + + /* Check if typename is a direct ancestor of type */ + while (type) { + TypeImpl *ti = type_get_instance(type); + + if (ti->type == target_type) { + return true; + } + + type = type_get_by_name(ti->parent); + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + Interface *iface = i->data; + + if (object_is_type(OBJECT(iface), typename)) { + return true; + } + } + + return false; +} + +Object *object_dynamic_cast(Object *obj, const char *typename) +{ + GSList *i; + + /* Check if typename is a direct ancestor */ + if (object_is_type(obj, typename)) { + return obj; + } + + /* Check if obj has an interface of typename */ + for (i = obj->interfaces; i; i = i->next) { + Interface *iface = i->data; + + if (object_is_type(OBJECT(iface), typename)) { + return OBJECT(iface); + } + } + + /* Check if obj is an interface and it's containing object is a direct ancestor of typename */ + if (object_is_type(obj, TYPE_INTERFACE)) { + Interface *iface = INTERFACE(obj); + + if (object_is_type(iface->obj, typename)) { + return iface->obj; + } + } + + return NULL; +} + + +static void register_interface(void) +{ + static TypeInfo interface_info = { + .name = TYPE_INTERFACE, + .instance_size = sizeof(Interface), + .abstract = true, + }; + + type_register_static(&interface_info); +} + +device_init(register_interface); + +Object *object_dynamic_cast_assert(Object *obj, const char *typename) +{ + Object *inst; + + inst = object_dynamic_cast(obj, typename); + + if (!inst) { + fprintf(stderr, "Object %p is not an instance of type %s\n", obj, typename); + abort(); + } + + return inst; +} + +ObjectClass *object_check_class(ObjectClass *class, const char *typename) +{ + Type target_type = type_get_by_name(typename); + Type type = class->type; + + while (type) { + TypeImpl *ti = type_get_instance(type); + + if (ti->type == target_type) { + return class; + } + + type = type_get_by_name(ti->parent); + } + + fprintf(stderr, "Object %p is not an instance of type %d\n", class, (int)type); + abort(); + + return NULL; +} + +const char *object_get_type(Object *obj) +{ + return type_get_name(obj->class->type); +} + +ObjectClass *object_get_class(Object *obj) +{ + return obj->class; +} + +ObjectClass *object_get_super(Object *obj) +{ + return type_get_instance(type_get_by_name(type_get_instance(obj->class->type)->parent))->class; +} + diff --git a/hw/object.h b/hw/object.h new file mode 100644 index 0000000..1ac2f92 --- /dev/null +++ b/hw/object.h @@ -0,0 +1,471 @@ +/* + * QEMU Object Model + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aligu...@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QOBJECT_H +#define QOBJECT_H + +#include "qemu-common.h" + +typedef uint64_t Type; + +typedef struct ObjectClass ObjectClass; +typedef struct Object Object; + +typedef struct TypeInfo TypeInfo; + +typedef struct InterfaceClass InterfaceClass; +typedef struct Interface Interface; +typedef struct InterfaceInfo InterfaceInfo; + +/** + * @ObjectClass: + * + * The base for all classes. The only thing that @ObjectClass contains is an + * integer type handle. + */ +struct ObjectClass +{ + /** + * @type the handle of the type for a class + */ + Type type; +}; + +/** + * @Object: + * + * The base for all objects. The first member of this object is a pointer to + * a @ObjectClass. Since C guarantees that the first member of a structure + * always begins at byte 0 of that structure, as long as any sub-object places + * its parent as the first member, we can cast directly to a @Object. + * + * As a result, @Object contains a reference to the objects type as its + * first member. This allows identification of the real type of the object at + * run time. + * + * @Object also contains a list of @Interfaces that this object + * implements. + */ +struct Object +{ + /** + * @class the type of the instantiated object. + */ + ObjectClass *class; + + /** + * @interfaces a list of @Interface objects implemented by this object + */ + GSList *interfaces; +}; + +/** + * @TypeInfo: + * + */ +struct TypeInfo +{ + /** + * @name the name of the type + */ + const char *name; + + /** + * @parent the name of the parent type + */ + const char *parent; + + /** + * Instance Initialization + * + * This functions manage the instance construction and destruction of a + * type. + */ + + /** + * @instance_size the size of the object (derivative of @Object). If + * @instance_size is 0, then the size of the object will be the size of the + * parent object. + */ + size_t instance_size; + + /** + * @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. + */ + void (*instance_init)(Object *obj); + + /** + * @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 function. + */ + void (*instance_finalize)(Object *obj); + + /** + * @abstract + * + * If this field is true, then the class is considered abstract and cannot + * be directly instantiated. + */ + bool abstract; + + /** + * Class Initialization + * + * Before an object is initialized, the class for the object must be + * initialized. There is only one class object for all instance objects + * that is created lazily. + * + * Classes are initialized by first initializing any parent classes (if + * necessary). After the parent class object has initialized, it will be + * copied into the current class object and any additional storage in the + * class object is zero filled. + * + * The effect of this is that classes automatically inherit any virtual + * function pointers that the parent class has already initialized. All + * other fields will be zero filled. + * + * After this initial copy, @base_init is invoked. This is meant to handle + * the case where a class may have a dynamic field that was copied via + * a shallow copy but needs to be deep copied. @base_init is called for + * each parent class but not for the class being instantiated. + * + * Once all of the parent classes have been initialized and their @base_init + * functions have been called, @class_init is called to let the class being + * instantiated provide default initialize for it's virtual functions. + */ + + /** + * @class_size the size of the class object (derivative of @ObjectClass) + * for this object. If @class_size is 0, then the size of the class will be + * assumed to be the size of the parent class. This allows a type to avoid + * implementing an explicit class type if they are not adding additional + * virtual functions. + */ + size_t class_size; + + /** + * @base_init + * + * This function is called after memcpy()'ing the base class into the new + * class to reinitialize any members that require deep copy. + */ + void (*base_init)(ObjectClass *klass); + + /** + * @base_finalize + * + * This function is called during a class's destruction and is meant to + * allow any dynamic parameters allocated by @base_init to be released. + */ + void (*base_finalize)(ObjectClass *klass); + + /** + * @class_init + * + * This function is called after all parent class initialization has occured + * to allow a class to set its default virtual method pointers. This is + * also the function to use to override virtual methods from a parent class. + */ + void (*class_init)(ObjectClass *klass); + + /** + * @class_finalize + * + * This function is called during class destruction and is meant to release + * and dynamic parameters allocated by @class_init. + */ + void (*class_finalize)(ObjectClass *klass); + + /** + * Interfaces + * + * Interfaces allow a limited form of multiple inheritance. Instances are + * similar to normal types except for the fact that are only defined by + * their classes and never carry any state. You can cast an object to one + * of its @Interface types and vice versa. + */ + + /** + * @interfaces the list of interfaces associated with this type. This + * should point to a static array that's terminated with a zero filled + * element. + */ + InterfaceInfo *interfaces; +}; + +/** + * @OBJECT + * + * Converts an object to a @Object. Since all objects are @Objects, + * this function will always succeed. + */ +#define OBJECT(obj) \ + ((Object *)(obj)) + +/** + * @OBJECT_CHECK + * + * A type safe version of @object_dynamic_cast_assert. Typically each class + * will define a macro based on this type to perform type safe dynamic_casts to + * this object type. + * + * If an invalid object is passed to this function, a run time assert will be + * generated. + */ +#define OBJECT_CHECK(type, obj, name) \ + ((type *)object_dynamic_cast_assert((Object *)(obj), (name))) + +/** + * @OBJECT_CLASS_CHECK + * + * A type safe version of @object_check_class. This macro is typically wrapped + * by each type to perform type safe casts of a class to a specific class type. + */ +#define OBJECT_CLASS_CHECK(class, obj, name) \ + ((class *)object_check_class((ObjectClass *)(obj), (name))) + +/** + * @OBJECT_GET_CLASS + * + * This function will return a specific class for a given object. Its generally + * used by each type to provide a type safe macro to get a specific class type + * from an object. + */ +#define OBJECT_GET_CLASS(class, obj, name) \ + OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name) + +/** + * @Interface: + * + * The base for all Interfaces. This is a subclass of Object. Subclasses + * of @Interface should never have an instance that contains anything other + * than a single @Interface member. + */ +struct Interface +{ + /** + * @parent base class + */ + Object parent; + + /* private */ + + /** + * @obj a pointer to the object that implements this interface. This is + * used to allow casting from an interface to the base object. + */ + Object *obj; +}; + +/** + * @InterfaceClass: + * + * The class for all interfaces. Subclasses of this class should only add + * virtual methods. + */ +struct InterfaceClass +{ + /** + * @parent_class the base class + */ + ObjectClass parent_class; +}; + +/** + * @InterfaceInfo: + * + * The information associated with an interface. + */ +struct InterfaceInfo +{ + /** + * @type the name of the interface + */ + const char *type; + + /** + * @interface_initfn is called during class initialization and is used to + * initialize an interface associated with a class. This function should + * initialize any default virtual functions for a class and/or override + * virtual functions in a parent class. + */ + void (*interface_initfn)(ObjectClass *class); +}; + +#define TYPE_INTERFACE "interface" +#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE) + +/** + * @object_new: + * + * This function will initialize a new object using heap allocated memory. This + * function should be paired with @object_delete to free the resources + * associated with the object. + * + * @typename: The name of the type of the object to instantiate + * + * Returns: The newly allocated and instantiated object. + * + */ +Object *object_new(const char *typename); + +/** + * @object_delete: + * + * Finalize an object and then free the memory associated with it. This should + * be paired with @object_new to free the resources associated with an object. + * + * @obj: The object to free. + * + */ +void object_delete(Object *obj); + +/** + * @object_initialize: + * + * This function will initialize an object. The memory for the object should + * have already been allocated. + * + * @obj: A pointer to the memory to be used for the object. + * + * @typename: The name of the type of the object to instantiate + * + */ +void object_initialize(void *obj, const char *typename); + +/** + * @object_finalize: + * + * This function destroys and object without freeing the memory associated with + * it. + * + * @obj: The object to finalize. + * + */ +void object_finalize(void *obj); + +/** + * @object_dynamic_cast: + * + * This function will determine if @obj is-a @typename. @obj can refer to an + * object or an interface associated with an object. + * + * @obj: The object to cast. + * + * @typename: The @typename + * + * Returns: + * + */ +Object *object_dynamic_cast(Object *obj, const char *typename); + +/** + * @object_dynamic_cast_assert: + * + * @obj: + * + * @typename: + * + * Returns: + * + */ +Object *object_dynamic_cast_assert(Object *obj, const char *typename); + +/** + * @object_is_type: + * + * @obj: + * + * @typename: + * + * Returns: + * + */ +bool object_is_type(Object *obj, const char *typename); + +/** + * @object_get_class: + * + * @obj: + * + * Returns: + * + */ +ObjectClass *object_get_class(Object *obj); + +/** + * @object_get_type: + * + * @obj: + * + * Returns: + */ +const char *object_get_type(Object *obj); + +/** + * @object_get_super: + * + * @obj: + * + * Returns: + */ +ObjectClass *object_get_super(Object *obj); + +/**/ + +/** + * @type_register_static: + * + * @info: + * + * Returns: + */ +Type type_register_static(const TypeInfo *info); + +/** + * @object_check_class: + * + * @obj: + * + * @typename: + * + * Returns: + */ +ObjectClass *object_check_class(ObjectClass *obj, const char *typename); + +/** + * @type_get_by_name: + * + * @name: + * + * Returns: + */ +Type type_get_by_name(const char *name); + +/** + * @type_get_name: + * + * @type: + * + * Returns: + */ +const char *type_get_name(Type type); + +#endif diff --git a/hw/qdev.h b/hw/qdev.h index 6e18427..0702b18 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -6,6 +6,7 @@ #include "qemu-char.h" #include "qemu-option.h" #include "qapi/qapi-visit-core.h" +#include "qobject.h" typedef struct Property Property; @@ -66,9 +67,15 @@ typedef struct DeviceProperty QTAILQ_ENTRY(DeviceProperty) node; } DeviceProperty; +typedef struct DeviceClass { + QObjectClass parent_class; +} DeviceClass; + /* This structure should not be accessed directly. We declare it here so that it can be embedded in individual device state structures. */ struct DeviceState { + QObject parent_obj; + const char *id; enum DevState state; QemuOpts *opts; diff --git a/hw/qobject.c b/hw/qobject.c deleted file mode 100644 index 54398ab..0000000 --- a/hw/qobject.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * QEMU Object Model - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aligu...@us.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include "qobject.h" - -#define MAX_INTERFACES 32 - -typedef struct QInterfaceImpl -{ - const char *parent; - void (*interface_initfn)(QObjectClass *class); - QType type; -} QInterfaceImpl; - -typedef struct QTypeImpl -{ - const char *name; - QType type; - - size_t class_size; - - size_t instance_size; - - void (*base_init)(QObjectClass *klass); - void (*base_finalize)(QObjectClass *klass); - - void (*class_init)(QObjectClass *klass); - void (*class_finalize)(QObjectClass *klass); - - void (*instance_init)(QObject *obj); - void (*instance_finalize)(QObject *obj); - - bool abstract; - - const char *parent; - - QObjectClass *class; - - int num_interfaces; - QInterfaceImpl interfaces[MAX_INTERFACES]; -} QTypeImpl; - -static int num_types = 1; -static QTypeImpl type_table[1024]; - -QType qtype_register_static(const QTypeInfo *info) -{ - QType type = num_types++; - QTypeImpl *ti; - - ti = &type_table[type]; - - assert(info->name != NULL); - - ti->name = info->name; - ti->parent = info->parent; - ti->type = type; - - ti->class_size = info->class_size; - ti->instance_size = info->instance_size; - - ti->base_init = info->base_init; - ti->base_finalize = info->base_finalize; - - ti->class_init = info->class_init; - ti->class_finalize = info->class_finalize; - - ti->instance_init = info->instance_init; - ti->instance_finalize = info->instance_finalize; - - ti->abstract = info->abstract; - - if (info->interfaces) { - int i; - - for (i = 0; info->interfaces[i].type; i++) { - ti->interfaces[i].parent = info->interfaces[i].type; - ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; - ti->num_interfaces++; - } - } - - return type; -} - -static QType qtype_register_anonymous(const QTypeInfo *info) -{ - QType type = num_types++; - QTypeImpl *ti; - char buffer[32]; - static int count; - - ti = &type_table[type]; - - snprintf(buffer, sizeof(buffer), "<anonymous-%d>", count++); - ti->name = g_strdup(buffer); - ti->parent = g_strdup(info->parent); - ti->type = type; - - ti->class_size = info->class_size; - ti->instance_size = info->instance_size; - - ti->base_init = info->base_init; - ti->base_finalize = info->base_finalize; - - ti->class_init = info->class_init; - ti->class_finalize = info->class_finalize; - - ti->instance_init = info->instance_init; - ti->instance_finalize = info->instance_finalize; - - if (info->interfaces) { - int i; - - for (i = 0; info->interfaces[i].type; i++) { - ti->interfaces[i].parent = info->interfaces[i].type; - ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; - ti->num_interfaces++; - } - } - - return type; -} - -static QTypeImpl *qtype_get_instance(QType type) -{ - assert(type != 0); - assert(type < num_types); - - return &type_table[type]; -} - -QType qtype_get_by_name(const char *name) -{ - int i; - - if (name == NULL) { - return 0; - } - - for (i = 1; i < num_types; i++) { - if (strcmp(name, type_table[i].name) == 0) { - return i; - } - } - - return 0; -} - -static void qtype_class_base_init(QTypeImpl *base_ti, const char *typename) -{ - QTypeImpl *ti; - - if (!typename) { - return; - } - - ti = qtype_get_instance(qtype_get_by_name(typename)); - - qtype_class_base_init(base_ti, ti->parent); - - if (ti->base_init) { - ti->base_init(base_ti->class); - } -} - -static size_t qtype_class_get_size(QTypeImpl *ti) -{ - if (ti->class_size) { - return ti->class_size; - } - - if (ti->parent) { - return qtype_class_get_size(qtype_get_instance(qtype_get_by_name(ti->parent))); - } - - return sizeof(QObjectClass); -} - -static void qtype_class_interface_init(QTypeImpl *ti, QInterfaceImpl *iface) -{ - QTypeInfo info = { - .instance_size = sizeof(QInterface), - .parent = iface->parent, - .class_size = sizeof(QInterfaceClass), - .class_init = iface->interface_initfn, - .abstract = true, - }; - - iface->type = qtype_register_anonymous(&info); -} - -static void qtype_class_init(QTypeImpl *ti) -{ - size_t class_size = sizeof(QObjectClass); - int i; - - if (ti->class) { - return; - } - - ti->class_size = qtype_class_get_size(ti); - - ti->class = g_malloc0(ti->class_size); - ti->class->type = ti->type; - - if (ti->parent) { - QTypeImpl *ti_parent; - - ti_parent = qtype_get_instance(qtype_get_by_name(ti->parent)); - - qtype_class_init(ti_parent); - - class_size = ti_parent->class_size; - assert(ti_parent->class_size <= ti->class_size); - - memcpy((void *)ti->class + sizeof(QObjectClass), - (void *)ti_parent->class + sizeof(QObjectClass), - ti_parent->class_size - sizeof(QObjectClass)); - } - - memset((void *)ti->class + class_size, 0, ti->class_size - class_size); - - qtype_class_base_init(ti, ti->parent); - - for (i = 0; i < ti->num_interfaces; i++) { - qtype_class_interface_init(ti, &ti->interfaces[i]); - } - - if (ti->class_init) { - ti->class_init(ti->class); - } -} - -static void qobject_interface_init(QObject *obj, QInterfaceImpl *iface) -{ - QTypeImpl *ti = qtype_get_instance(iface->type); - QInterface *iface_obj; - - iface_obj = QINTERFACE(qobject_new(ti->name)); - iface_obj->obj = obj; - - obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); -} - -static void qobject_init(QObject *obj, const char *typename) -{ - QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); - int i; - - if (ti->parent) { - qobject_init(obj, ti->parent); - } - - for (i = 0; i < ti->num_interfaces; i++) { - qobject_interface_init(obj, &ti->interfaces[i]); - } - - if (ti->instance_init) { - ti->instance_init(obj); - } -} - -void qobject_initialize(void *data, const char *typename) -{ - QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); - QObject *obj = data; - - g_assert(ti->instance_size >= sizeof(QObjectClass)); - - qtype_class_init(ti); - - g_assert(ti->abstract == false); - - memset(obj, 0, ti->instance_size); - - obj->class = ti->class; - - qobject_init(obj, typename); -} - -static void qobject_deinit(QObject *obj, const char *typename) -{ - QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); - - if (ti->instance_finalize) { - ti->instance_finalize(obj); - } - - while (obj->interfaces) { - QInterface *iface_obj = obj->interfaces->data; - obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); - qobject_delete(QOBJECT(iface_obj)); - } - - if (ti->parent) { - qobject_init(obj, ti->parent); - } -} - -void qobject_finalize(void *data) -{ - QObject *obj = data; - QTypeImpl *ti = qtype_get_instance(obj->class->type); - - qobject_deinit(obj, ti->name); -} - -const char *qtype_get_name(QType type) -{ - QTypeImpl *ti = qtype_get_instance(type); - return ti->name; -} - -QObject *qobject_new(const char *typename) -{ - QTypeImpl *ti = qtype_get_instance(qtype_get_by_name(typename)); - QObject *obj; - - obj = g_malloc(ti->instance_size); - qobject_initialize(obj, typename); - - return obj; -} - -void qobject_delete(QObject *obj) -{ - qobject_finalize(obj); - g_free(obj); -} - -bool qobject_is_type(QObject *obj, const char *typename) -{ - QType target_type = qtype_get_by_name(typename); - QType type = obj->class->type; - GSList *i; - - /* Check if typename is a direct ancestor of type */ - while (type) { - QTypeImpl *ti = qtype_get_instance(type); - - if (ti->type == target_type) { - return true; - } - - type = qtype_get_by_name(ti->parent); - } - - /* Check if obj has an interface of typename */ - for (i = obj->interfaces; i; i = i->next) { - QInterface *iface = i->data; - - if (qobject_is_type(QOBJECT(iface), typename)) { - return true; - } - } - - return false; -} - -QObject *qobject_dynamic_cast(QObject *obj, const char *typename) -{ - GSList *i; - - /* Check if typename is a direct ancestor */ - if (qobject_is_type(obj, typename)) { - return obj; - } - - /* Check if obj has an interface of typename */ - for (i = obj->interfaces; i; i = i->next) { - QInterface *iface = i->data; - - if (qobject_is_type(QOBJECT(iface), typename)) { - return QOBJECT(iface); - } - } - - /* Check if obj is an interface and it's containing object is a direct ancestor of typename */ - if (qobject_is_type(obj, TYPE_QINTERFACE)) { - QInterface *iface = QINTERFACE(obj); - - if (qobject_is_type(iface->obj, typename)) { - return iface->obj; - } - } - - return NULL; -} - - -static void register_interface(void) -{ - static QTypeInfo interface_info = { - .name = TYPE_QINTERFACE, - .instance_size = sizeof(QInterface), - .abstract = true, - }; - - qtype_register_static(&interface_info); -} - -device_init(register_interface); - -QObject *qobject_dynamic_cast_assert(QObject *obj, const char *typename) -{ - QObject *inst; - - inst = qobject_dynamic_cast(obj, typename); - - if (!inst) { - fprintf(stderr, "Object %p is not an instance of type %s\n", obj, typename); - abort(); - } - - return inst; -} - -QObjectClass *qobject_check_class(QObjectClass *class, const char *typename) -{ - QType target_type = qtype_get_by_name(typename); - QType type = class->type; - - while (type) { - QTypeImpl *ti = qtype_get_instance(type); - - if (ti->type == target_type) { - return class; - } - - type = qtype_get_by_name(ti->parent); - } - - fprintf(stderr, "Object %p is not an instance of type %d\n", class, (int)type); - abort(); - - return NULL; -} - -const char *qobject_get_type(QObject *obj) -{ - return qtype_get_name(obj->class->type); -} - -QObjectClass *qobject_get_class(QObject *obj) -{ - return obj->class; -} - -QObjectClass *qobject_get_super(QObject *obj) -{ - return qtype_get_instance(qtype_get_by_name(qtype_get_instance(obj->class->type)->parent))->class; -} - diff --git a/hw/qobject.h b/hw/qobject.h deleted file mode 100644 index f20ed1c..0000000 --- a/hw/qobject.h +++ /dev/null @@ -1,471 +0,0 @@ -/* - * QEMU Object Model - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori <aligu...@us.ibm.com> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#ifndef QOBJECT_H -#define QOBJECT_H - -#include "qemu-common.h" - -typedef uint64_t QType; - -typedef struct QObjectClass QObjectClass; -typedef struct QObject QObject; - -typedef struct QTypeInfo QTypeInfo; - -typedef struct QInterfaceClass QInterfaceClass; -typedef struct QInterface QInterface; -typedef struct QInterfaceInfo QInterfaceInfo; - -/** - * @QObjectClass: - * - * The base for all classes. The only thing that @QObjectClass contains is an - * integer type handle. - */ -struct QObjectClass -{ - /** - * @type the handle of the type for a class - */ - QType type; -}; - -/** - * @QObject: - * - * The base for all objects. The first member of this object is a pointer to - * a @QObjectClass. Since C guarantees that the first member of a structure - * always begins at byte 0 of that structure, as long as any sub-object places - * its parent as the first member, we can cast directly to a @QObject. - * - * As a result, @QObject contains a reference to the objects type as its - * first member. This allows identification of the real type of the object at - * run time. - * - * @QObject also contains a list of @QInterfaces that this object - * implements. - */ -struct QObject -{ - /** - * @class the type of the instantiated object. - */ - QObjectClass *class; - - /** - * @interfaces a list of @QInterface objects implemented by this object - */ - GSList *interfaces; -}; - -/** - * @QTypeInfo: - * - */ -struct QTypeInfo -{ - /** - * @name the name of the type - */ - const char *name; - - /** - * @parent the name of the parent type - */ - const char *parent; - - /** - * Instance Initialization - * - * This functions manage the instance construction and destruction of a - * type. - */ - - /** - * @instance_size the size of the object (derivative of @QObject). If - * @instance_size is 0, then the size of the object will be the size of the - * parent object. - */ - size_t instance_size; - - /** - * @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. - */ - void (*instance_init)(QObject *obj); - - /** - * @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 function. - */ - void (*instance_finalize)(QObject *obj); - - /** - * @abstract - * - * If this field is true, then the class is considered abstract and cannot - * be directly instantiated. - */ - bool abstract; - - /** - * Class Initialization - * - * Before an object is initialized, the class for the object must be - * initialized. There is only one class object for all instance objects - * that is created lazily. - * - * Classes are initialized by first initializing any parent classes (if - * necessary). After the parent class object has initialized, it will be - * copied into the current class object and any additional storage in the - * class object is zero filled. - * - * The effect of this is that classes automatically inherit any virtual - * function pointers that the parent class has already initialized. All - * other fields will be zero filled. - * - * After this initial copy, @base_init is invoked. This is meant to handle - * the case where a class may have a dynamic field that was copied via - * a shallow copy but needs to be deep copied. @base_init is called for - * each parent class but not for the class being instantiated. - * - * Once all of the parent classes have been initialized and their @base_init - * functions have been called, @class_init is called to let the class being - * instantiated provide default initialize for it's virtual functions. - */ - - /** - * @class_size the size of the class object (derivative of @QObjectClass) - * for this object. If @class_size is 0, then the size of the class will be - * assumed to be the size of the parent class. This allows a type to avoid - * implementing an explicit class type if they are not adding additional - * virtual functions. - */ - size_t class_size; - - /** - * @base_init - * - * This function is called after memcpy()'ing the base class into the new - * class to reinitialize any members that require deep copy. - */ - void (*base_init)(QObjectClass *klass); - - /** - * @base_finalize - * - * This function is called during a class's destruction and is meant to - * allow any dynamic parameters allocated by @base_init to be released. - */ - void (*base_finalize)(QObjectClass *klass); - - /** - * @class_init - * - * This function is called after all parent class initialization has occured - * to allow a class to set its default virtual method pointers. This is - * also the function to use to override virtual methods from a parent class. - */ - void (*class_init)(QObjectClass *klass); - - /** - * @class_finalize - * - * This function is called during class destruction and is meant to release - * and dynamic parameters allocated by @class_init. - */ - void (*class_finalize)(QObjectClass *klass); - - /** - * QInterfaces - * - * QInterfaces allow a limited form of multiple inheritance. Instances are - * similar to normal types except for the fact that are only defined by - * their classes and never carry any state. You can cast an object to one - * of its @QInterface types and vice versa. - */ - - /** - * @interfaces the list of interfaces associated with this type. This - * should point to a static array that's terminated with a zero filled - * element. - */ - QInterfaceInfo *interfaces; -}; - -/** - * @QOBJECT - * - * Converts an object to a @QObject. Since all objects are @QObjects, - * this function will always succeed. - */ -#define QOBJECT(obj) \ - ((QObject *)(obj)) - -/** - * @QOBJECT_CHECK - * - * A type safe version of @qobject_dynamic_cast_assert. Typically each class - * will define a macro based on this type to perform type safe dynamic_casts to - * this object type. - * - * If an invalid object is passed to this function, a run time assert will be - * generated. - */ -#define QOBJECT_CHECK(type, obj, name) \ - ((type *)qobject_dynamic_cast_assert((QObject *)(obj), (name))) - -/** - * @QOBJECT_CLASS_CHECK - * - * A type safe version of @qobject_check_class. This macro is typically wrapped - * by each type to perform type safe casts of a class to a specific class type. - */ -#define QOBJECT_CLASS_CHECK(class, obj, name) \ - ((class *)qobject_check_class((QObjectClass *)(obj), (name))) - -/** - * @QOBJECT_GET_CLASS - * - * This function will return a specific class for a given object. Its generally - * used by each type to provide a type safe macro to get a specific class type - * from an object. - */ -#define QOBJECT_GET_CLASS(class, obj, name) \ - QOBJECT_CLASS_CHECK(class, qobject_get_class(QOBJECT(obj)), name) - -/** - * @QQInterface: - * - * The base for all QInterfaces. This is a subclass of QObject. Subclasses - * of @QInterface should never have an instance that contains anything other - * than a single @QInterface member. - */ -struct QInterface -{ - /** - * @parent base class - */ - QObject parent; - - /* private */ - - /** - * @obj a pointer to the object that implements this interface. This is - * used to allow casting from an interface to the base object. - */ - QObject *obj; -}; - -/** - * @QInterfaceClass: - * - * The class for all interfaces. Subclasses of this class should only add - * virtual methods. - */ -struct QInterfaceClass -{ - /** - * @parent_class the base class - */ - QObjectClass parent_class; -}; - -/** - * @QInterfaceInfo: - * - * The information associated with an interface. - */ -struct QInterfaceInfo -{ - /** - * @type the name of the interface - */ - const char *type; - - /** - * @interface_initfn is called during class initialization and is used to - * initialize an interface associated with a class. This function should - * initialize any default virtual functions for a class and/or override - * virtual functions in a parent class. - */ - void (*interface_initfn)(QObjectClass *class); -}; - -#define TYPE_QINTERFACE "interface" -#define QINTERFACE(obj) QOBJECT_CHECK(QInterface, obj, TYPE_QINTERFACE) - -/** - * @qobject_new: - * - * This function will initialize a new object using heap allocated memory. This - * function should be paired with @qobject_delete to free the resources - * associated with the object. - * - * @typename: The name of the type of the object to instantiate - * - * Returns: The newly allocated and instantiated object. - * - */ -QObject *qobject_new(const char *typename); - -/** - * @qobject_delete: - * - * Finalize an object and then free the memory associated with it. This should - * be paired with @qobject_new to free the resources associated with an object. - * - * @obj: The object to free. - * - */ -void qobject_delete(QObject *obj); - -/** - * @qobject_initialize: - * - * This function will initialize an object. The memory for the object should - * have already been allocated. - * - * @obj: A pointer to the memory to be used for the object. - * - * @typename: The name of the type of the object to instantiate - * - */ -void qobject_initialize(void *obj, const char *typename); - -/** - * @qobject_finalize: - * - * This function destroys and object without freeing the memory associated with - * it. - * - * @obj: The object to finalize. - * - */ -void qobject_finalize(void *obj); - -/** - * @qobject_dynamic_cast: - * - * This function will determine if @obj is-a @typename. @obj can refer to an - * object or an interface associated with an object. - * - * @obj: The object to cast. - * - * @typename: The @typename - * - * Returns: - * - */ -QObject *qobject_dynamic_cast(QObject *obj, const char *typename); - -/** - * @qobject_dynamic_cast_assert: - * - * @obj: - * - * @typename: - * - * Returns: - * - */ -QObject *qobject_dynamic_cast_assert(QObject *obj, const char *typename); - -/** - * @qobject_is_type: - * - * @obj: - * - * @typename: - * - * Returns: - * - */ -bool qobject_is_type(QObject *obj, const char *typename); - -/** - * @qobject_get_class: - * - * @obj: - * - * Returns: - * - */ -QObjectClass *qobject_get_class(QObject *obj); - -/** - * @qobject_get_type: - * - * @obj: - * - * Returns: - */ -const char *qobject_get_type(QObject *obj); - -/** - * @qobject_get_super: - * - * @obj: - * - * Returns: - */ -QObjectClass *qobject_get_super(QObject *obj); - -/**/ - -/** - * @qtype_register_static: - * - * @info: - * - * Returns: - */ -QType qtype_register_static(const QTypeInfo *info); - -/** - * @qobject_check_class: - * - * @obj: - * - * @typename: - * - * Returns: - */ -QObjectClass *qobject_check_class(QObjectClass *obj, const char *typename); - -/** - * @qtype_get_by_name: - * - * @name: - * - * Returns: - */ -QType qtype_get_by_name(const char *name); - -/** - * @qtype_get_name: - * - * @type: - * - * Returns: - */ -const char *qtype_get_name(QType type); - -#endif -- 1.7.4.1