diff options
Diffstat (limited to 'qom')
-rw-r--r-- | qom/object.c | 148 |
1 files changed, 104 insertions, 44 deletions
diff --git a/qom/object.c b/qom/object.c index c0decb6e96..d7515697a3 100644 --- a/qom/object.c +++ b/qom/object.c @@ -67,6 +67,10 @@ struct TypeImpl InterfaceImpl interfaces[MAX_INTERFACES]; }; +struct ObjectPropertyIterator { + GHashTableIter iter; +}; + static Type type_interface; static GHashTable *type_table_get(void) @@ -261,7 +265,7 @@ static void type_initialize(TypeImpl *ti) GSList *e; int i; - g_assert(parent->class_size <= ti->class_size); + g_assert_cmpint(parent->class_size, <=, ti->class_size); memcpy(ti->class, parent->class, parent->class_size); ti->class->interfaces = NULL; @@ -326,6 +330,16 @@ static void object_post_init_with_type(Object *obj, TypeImpl *ti) } } +static void object_property_free(gpointer data) +{ + ObjectProperty *prop = data; + + g_free(prop->name); + g_free(prop->type); + g_free(prop->description); + g_free(prop); +} + void object_initialize_with_type(void *data, size_t size, TypeImpl *type) { Object *obj = data; @@ -333,14 +347,15 @@ void object_initialize_with_type(void *data, size_t size, TypeImpl *type) g_assert(type != NULL); type_initialize(type); - g_assert(type->instance_size >= sizeof(Object)); + g_assert_cmpint(type->instance_size, >=, sizeof(Object)); g_assert(type->abstract == false); - g_assert(size >= type->instance_size); + g_assert_cmpint(size, >=, type->instance_size); memset(obj, 0, type->instance_size); obj->class = type->class; object_ref(obj); - QTAILQ_INIT(&obj->properties); + obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, object_property_free); object_init_with_type(obj, type); object_post_init_with_type(obj, type); } @@ -359,29 +374,51 @@ static inline bool object_property_is_child(ObjectProperty *prop) static void object_property_del_all(Object *obj) { - while (!QTAILQ_EMPTY(&obj->properties)) { - ObjectProperty *prop = QTAILQ_FIRST(&obj->properties); - - QTAILQ_REMOVE(&obj->properties, prop, node); - - if (prop->release) { - prop->release(obj, prop->name, prop->opaque); + ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; + bool released; + + do { + released = false; + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + released = true; + break; + } + g_hash_table_iter_remove(&iter); } + } while (released); - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); - } + g_hash_table_unref(obj->properties); } static void object_property_del_child(Object *obj, Object *child, Error **errp) { ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; - QTAILQ_FOREACH(prop, &obj->properties, node) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (object_property_is_child(prop) && prop->opaque == child) { + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + } + break; + } + } + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; if (object_property_is_child(prop) && prop->opaque == child) { - object_property_del(obj, prop->name, errp); + g_hash_table_iter_remove(&iter); break; } } @@ -413,7 +450,7 @@ static void object_finalize(void *data) object_property_del_all(obj); object_deinit(obj, ti); - g_assert(obj->ref == 0); + g_assert_cmpint(obj->ref, ==, 0); if (obj->free) { obj->free(obj); } @@ -779,10 +816,12 @@ static int do_object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), void *opaque, bool recurse) { - ObjectProperty *prop, *next; + GHashTableIter iter; + ObjectProperty *prop; int ret = 0; - QTAILQ_FOREACH_SAFE(prop, &obj->properties, node, next) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (object_property_is_child(prop)) { Object *child = prop->opaque; @@ -833,7 +872,7 @@ void object_ref(Object *obj) if (!obj) { return; } - atomic_inc(&obj->ref); + atomic_inc(&obj->ref); } void object_unref(Object *obj) @@ -841,7 +880,7 @@ void object_unref(Object *obj) if (!obj) { return; } - g_assert(obj->ref > 0); + g_assert_cmpint(obj->ref, >, 0); /* parent always holds a reference to its children */ if (atomic_fetch_dec(&obj->ref) == 1) { @@ -879,13 +918,11 @@ object_property_add(Object *obj, const char *name, const char *type, return ret; } - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - error_setg(errp, "attempt to add duplicate property '%s'" + if (g_hash_table_lookup(obj->properties, name) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s'" " to object (type '%s')", name, object_get_typename(obj)); - return NULL; - } + return NULL; } prop = g_malloc0(sizeof(*prop)); @@ -898,7 +935,7 @@ object_property_add(Object *obj, const char *name, const char *type, prop->release = release; prop->opaque = opaque; - QTAILQ_INSERT_TAIL(&obj->properties, prop, node); + g_hash_table_insert(obj->properties, prop->name, prop); return prop; } @@ -907,33 +944,52 @@ ObjectProperty *object_property_find(Object *obj, const char *name, { ObjectProperty *prop; - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - return prop; - } + prop = g_hash_table_lookup(obj->properties, name); + if (prop) { + return prop; } error_setg(errp, "Property '.%s' not found", name); return NULL; } +ObjectPropertyIterator *object_property_iter_init(Object *obj) +{ + ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1); + g_hash_table_iter_init(&ret->iter, obj->properties); + return ret; +} + +void object_property_iter_free(ObjectPropertyIterator *iter) +{ + if (!iter) { + return; + } + g_free(iter); +} + +ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) +{ + gpointer key, val; + if (!g_hash_table_iter_next(&iter->iter, &key, &val)) { + return NULL; + } + return val; +} + void object_property_del(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); - if (prop == NULL) { + ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); + + if (!prop) { + error_setg(errp, "Property '.%s' not found", name); return; } if (prop->release) { prop->release(obj, name, prop->opaque); } - - QTAILQ_REMOVE(&obj->properties, prop, node); - - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); + g_hash_table_remove(obj->properties, name); } void object_property_get(Object *obj, Visitor *v, const char *name, @@ -1453,11 +1509,13 @@ void object_property_add_const_link(Object *obj, const char *name, gchar *object_get_canonical_path_component(Object *obj) { ObjectProperty *prop = NULL; + GHashTableIter iter; g_assert(obj); g_assert(obj->parent != NULL); - QTAILQ_FOREACH(prop, &obj->parent->properties, node) { + g_hash_table_iter_init(&iter, obj->parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (!object_property_is_child(prop)) { continue; } @@ -1541,11 +1599,13 @@ static Object *object_resolve_partial_path(Object *parent, bool *ambiguous) { Object *obj; + GHashTableIter iter; ObjectProperty *prop; obj = object_resolve_abs_path(parent, parts, typename, 0); - QTAILQ_FOREACH(prop, &parent->properties, node) { + g_hash_table_iter_init(&iter, parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { Object *found; if (!object_property_is_child(prop)) { |