mirror of https://github.com/xemu-project/xemu.git
qom: add a generic mechanism to resolve paths
It may be desirable to have custom link<> properties that do more than just store an object. Even the addition of a "check" function is not enough if setting the link has side effects or if a non-standard reference counting is preferrable. Avoid the assumption that the opaque field of a link<> is a LinkProperty struct, by adding a generic "resolve" callback to ObjectProperty. This fixes aliases of link properties. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
ef7c7ff6d4
commit
64607d0881
|
@ -303,6 +303,25 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
|
|||
const char *name,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* ObjectPropertyResolve:
|
||||
* @obj: the object that owns the property
|
||||
* @opaque: the opaque registered with the property
|
||||
* @part: the name of the property
|
||||
*
|
||||
* Resolves the #Object corresponding to property @part.
|
||||
*
|
||||
* The returned object can also be used as a starting point
|
||||
* to resolve a relative path starting with "@part".
|
||||
*
|
||||
* Returns: If @path is the path that led to @obj, the function
|
||||
* returns the #Object corresponding to "@path/@part".
|
||||
* If "@path/@part" is not a valid object path, it returns #NULL.
|
||||
*/
|
||||
typedef Object *(ObjectPropertyResolve)(Object *obj,
|
||||
void *opaque,
|
||||
const char *part);
|
||||
|
||||
/**
|
||||
* ObjectPropertyRelease:
|
||||
* @obj: the object that owns the property
|
||||
|
@ -321,6 +340,7 @@ typedef struct ObjectProperty
|
|||
gchar *type;
|
||||
ObjectPropertyAccessor *get;
|
||||
ObjectPropertyAccessor *set;
|
||||
ObjectPropertyResolve *resolve;
|
||||
ObjectPropertyRelease *release;
|
||||
void *opaque;
|
||||
|
||||
|
@ -787,8 +807,12 @@ void object_unref(Object *obj);
|
|||
* destruction. This may be NULL.
|
||||
* @opaque: an opaque pointer to pass to the callbacks for the property
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Returns: The #ObjectProperty; this can be used to set the @resolve
|
||||
* callback for child and link properties.
|
||||
*/
|
||||
void object_property_add(Object *obj, const char *name, const char *type,
|
||||
ObjectProperty *object_property_add(Object *obj, const char *name,
|
||||
const char *type,
|
||||
ObjectPropertyAccessor *get,
|
||||
ObjectPropertyAccessor *set,
|
||||
ObjectPropertyRelease *release,
|
||||
|
|
54
qom/object.c
54
qom/object.c
|
@ -356,11 +356,6 @@ static inline bool object_property_is_child(ObjectProperty *prop)
|
|||
return strstart(prop->type, "child<", NULL);
|
||||
}
|
||||
|
||||
static inline bool object_property_is_link(ObjectProperty *prop)
|
||||
{
|
||||
return strstart(prop->type, "link<", NULL);
|
||||
}
|
||||
|
||||
static void object_property_del_all(Object *obj)
|
||||
{
|
||||
while (!QTAILQ_EMPTY(&obj->properties)) {
|
||||
|
@ -728,7 +723,8 @@ void object_unref(Object *obj)
|
|||
}
|
||||
}
|
||||
|
||||
void object_property_add(Object *obj, const char *name, const char *type,
|
||||
ObjectProperty *
|
||||
object_property_add(Object *obj, const char *name, const char *type,
|
||||
ObjectPropertyAccessor *get,
|
||||
ObjectPropertyAccessor *set,
|
||||
ObjectPropertyRelease *release,
|
||||
|
@ -741,7 +737,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
|||
error_setg(errp, "attempt to add duplicate property '%s'"
|
||||
" to object (type '%s')", name,
|
||||
object_get_typename(obj));
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -756,6 +752,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
|||
prop->opaque = opaque;
|
||||
|
||||
QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
|
||||
return prop;
|
||||
}
|
||||
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||
|
@ -1028,6 +1025,11 @@ static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
|
|||
g_free(path);
|
||||
}
|
||||
|
||||
static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
|
||||
{
|
||||
return opaque;
|
||||
}
|
||||
|
||||
static void object_finalize_child_property(Object *obj, const char *name,
|
||||
void *opaque)
|
||||
{
|
||||
|
@ -1041,15 +1043,18 @@ void object_property_add_child(Object *obj, const char *name,
|
|||
{
|
||||
Error *local_err = NULL;
|
||||
gchar *type;
|
||||
ObjectProperty *op;
|
||||
|
||||
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
||||
|
||||
object_property_add(obj, name, type, object_get_child_property, NULL,
|
||||
op = object_property_add(obj, name, type, object_get_child_property, NULL,
|
||||
object_finalize_child_property, child, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
op->resolve = object_resolve_child_property;
|
||||
object_ref(child);
|
||||
g_assert(child->parent == NULL);
|
||||
child->parent = obj;
|
||||
|
@ -1163,6 +1168,13 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
|
|||
}
|
||||
}
|
||||
|
||||
static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
|
||||
{
|
||||
LinkProperty *lprop = opaque;
|
||||
|
||||
return *lprop->child;
|
||||
}
|
||||
|
||||
static void object_release_link_property(Object *obj, const char *name,
|
||||
void *opaque)
|
||||
{
|
||||
|
@ -1184,6 +1196,7 @@ void object_property_add_link(Object *obj, const char *name,
|
|||
Error *local_err = NULL;
|
||||
LinkProperty *prop = g_malloc(sizeof(*prop));
|
||||
gchar *full_type;
|
||||
ObjectProperty *op;
|
||||
|
||||
prop->child = child;
|
||||
prop->check = check;
|
||||
|
@ -1191,7 +1204,7 @@ void object_property_add_link(Object *obj, const char *name,
|
|||
|
||||
full_type = g_strdup_printf("link<%s>", type);
|
||||
|
||||
object_property_add(obj, name, full_type,
|
||||
op = object_property_add(obj, name, full_type,
|
||||
object_get_link_property,
|
||||
check ? object_set_link_property : NULL,
|
||||
object_release_link_property,
|
||||
|
@ -1200,8 +1213,12 @@ void object_property_add_link(Object *obj, const char *name,
|
|||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
g_free(prop);
|
||||
goto out;
|
||||
}
|
||||
|
||||
op->resolve = object_resolve_link_property;
|
||||
|
||||
out:
|
||||
g_free(full_type);
|
||||
}
|
||||
|
||||
|
@ -1260,11 +1277,8 @@ Object *object_resolve_path_component(Object *parent, const gchar *part)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (object_property_is_link(prop)) {
|
||||
LinkProperty *lprop = prop->opaque;
|
||||
return *lprop->child;
|
||||
} else if (object_property_is_child(prop)) {
|
||||
return prop->opaque;
|
||||
if (prop->resolve) {
|
||||
return prop->resolve(parent, prop->opaque, part);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1571,6 +1585,14 @@ static void property_set_alias(Object *obj, struct Visitor *v, void *opaque,
|
|||
object_property_set(prop->target_obj, v, prop->target_name, errp);
|
||||
}
|
||||
|
||||
static Object *property_resolve_alias(Object *obj, void *opaque,
|
||||
const gchar *part)
|
||||
{
|
||||
AliasProperty *prop = opaque;
|
||||
|
||||
return object_resolve_path_component(prop->target_obj, prop->target_name);
|
||||
}
|
||||
|
||||
static void property_release_alias(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
AliasProperty *prop = opaque;
|
||||
|
@ -1583,6 +1605,7 @@ void object_property_add_alias(Object *obj, const char *name,
|
|||
Error **errp)
|
||||
{
|
||||
AliasProperty *prop;
|
||||
ObjectProperty *op;
|
||||
ObjectProperty *target_prop;
|
||||
|
||||
target_prop = object_property_find(target_obj, target_name, errp);
|
||||
|
@ -1594,11 +1617,12 @@ void object_property_add_alias(Object *obj, const char *name,
|
|||
prop->target_obj = target_obj;
|
||||
prop->target_name = target_name;
|
||||
|
||||
object_property_add(obj, name, target_prop->type,
|
||||
op = object_property_add(obj, name, target_prop->type,
|
||||
property_get_alias,
|
||||
property_set_alias,
|
||||
property_release_alias,
|
||||
prop, errp);
|
||||
op->resolve = property_resolve_alias;
|
||||
}
|
||||
|
||||
static void object_instance_init(Object *obj)
|
||||
|
|
Loading…
Reference in New Issue