object: sure up reference counting
Now we have the following behavior: 1) object_new() returns an object with ref = 1 2) object_initialize() does not increase the reference count (ref may be 0). 3) object_deref() will finalize the object when ref = 0. it does not free the memory associated with the object. 4) both link and child properties correctly set the reference count. The expected usage is the following: 1) child devices should generally be created via object_initialize() using memory from the parent device. Adding the object as a child property will take ownership of the object and tie the child's life cycle to the parent. 2) If a child device is created via qdev_create() or some other form of object_new(), there must be an object_delete() call in the parent device's finalize function. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
d03d6b4e5c
commit
db85b575b9
16
qom/object.c
16
qom/object.c
@ -337,6 +337,8 @@ void object_finalize(void *data)
|
|||||||
|
|
||||||
object_deinit(obj, ti);
|
object_deinit(obj, ti);
|
||||||
object_property_del_all(obj);
|
object_property_del_all(obj);
|
||||||
|
|
||||||
|
g_assert(obj->ref == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *object_new_with_type(Type type)
|
Object *object_new_with_type(Type type)
|
||||||
@ -347,6 +349,7 @@ Object *object_new_with_type(Type type)
|
|||||||
|
|
||||||
obj = g_malloc(type->instance_size);
|
obj = g_malloc(type->instance_size);
|
||||||
object_initialize_with_type(obj, type);
|
object_initialize_with_type(obj, type);
|
||||||
|
object_ref(obj);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -360,7 +363,8 @@ Object *object_new(const char *typename)
|
|||||||
|
|
||||||
void object_delete(Object *obj)
|
void object_delete(Object *obj)
|
||||||
{
|
{
|
||||||
object_finalize(obj);
|
object_unref(obj);
|
||||||
|
g_assert(obj->ref == 0);
|
||||||
g_free(obj);
|
g_free(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,6 +683,14 @@ static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
|
|||||||
g_free(path);
|
g_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void object_finalize_child_property(Object *obj, const char *name,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
Object *child = opaque;
|
||||||
|
|
||||||
|
object_unref(child);
|
||||||
|
}
|
||||||
|
|
||||||
void object_property_add_child(Object *obj, const char *name,
|
void object_property_add_child(Object *obj, const char *name,
|
||||||
Object *child, Error **errp)
|
Object *child, Error **errp)
|
||||||
{
|
{
|
||||||
@ -687,7 +699,7 @@ void object_property_add_child(Object *obj, const char *name,
|
|||||||
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
||||||
|
|
||||||
object_property_add(obj, name, type, object_get_child_property,
|
object_property_add(obj, name, type, object_get_child_property,
|
||||||
NULL, NULL, child, errp);
|
NULL, object_finalize_child_property, child, errp);
|
||||||
|
|
||||||
object_ref(child);
|
object_ref(child);
|
||||||
g_assert(child->parent == NULL);
|
g_assert(child->parent == NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user