1 /* 2 * QEMU Object Model 3 * 4 * Copyright IBM, Corp. 2011 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/object.h" 14 #include "qemu-common.h" 15 16 #define MAX_INTERFACES 32 17 18 typedef struct InterfaceImpl InterfaceImpl; 19 typedef struct TypeImpl TypeImpl; 20 21 struct InterfaceImpl 22 { 23 const char *parent; 24 void (*interface_initfn)(ObjectClass *class, void *data); 25 TypeImpl *type; 26 }; 27 28 struct TypeImpl 29 { 30 const char *name; 31 32 size_t class_size; 33 34 size_t instance_size; 35 36 void (*class_init)(ObjectClass *klass, void *data); 37 void (*class_finalize)(ObjectClass *klass, void *data); 38 39 void *class_data; 40 41 void (*instance_init)(Object *obj); 42 void (*instance_finalize)(Object *obj); 43 44 bool abstract; 45 46 const char *parent; 47 TypeImpl *parent_type; 48 49 ObjectClass *class; 50 51 int num_interfaces; 52 InterfaceImpl interfaces[MAX_INTERFACES]; 53 }; 54 55 typedef struct Interface 56 { 57 Object parent; 58 Object *obj; 59 } Interface; 60 61 #define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE) 62 63 static GHashTable *type_table_get(void) 64 { 65 static GHashTable *type_table; 66 67 if (type_table == NULL) { 68 type_table = g_hash_table_new(g_str_hash, g_str_equal); 69 } 70 71 return type_table; 72 } 73 74 static void type_table_add(TypeImpl *ti) 75 { 76 g_hash_table_insert(type_table_get(), (void *)ti->name, ti); 77 } 78 79 static TypeImpl *type_table_lookup(const char *name) 80 { 81 return g_hash_table_lookup(type_table_get(), name); 82 } 83 84 TypeImpl *type_register(const TypeInfo *info) 85 { 86 TypeImpl *ti = g_malloc0(sizeof(*ti)); 87 88 g_assert(info->name != NULL); 89 90 if (type_table_lookup(info->name) != NULL) { 91 fprintf(stderr, "Registering `%s' which already exists\n", info->name); 92 abort(); 93 } 94 95 ti->name = g_strdup(info->name); 96 ti->parent = g_strdup(info->parent); 97 98 ti->class_size = info->class_size; 99 ti->instance_size = info->instance_size; 100 101 ti->class_init = info->class_init; 102 ti->class_finalize = info->class_finalize; 103 ti->class_data = info->class_data; 104 105 ti->instance_init = info->instance_init; 106 ti->instance_finalize = info->instance_finalize; 107 108 ti->abstract = info->abstract; 109 110 if (info->interfaces) { 111 int i; 112 113 for (i = 0; info->interfaces[i].type; i++) { 114 ti->interfaces[i].parent = info->interfaces[i].type; 115 ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn; 116 ti->num_interfaces++; 117 } 118 } 119 120 type_table_add(ti); 121 122 return ti; 123 } 124 125 TypeImpl *type_register_static(const TypeInfo *info) 126 { 127 return type_register(info); 128 } 129 130 static TypeImpl *type_get_by_name(const char *name) 131 { 132 if (name == NULL) { 133 return NULL; 134 } 135 136 return type_table_lookup(name); 137 } 138 139 static TypeImpl *type_get_parent(TypeImpl *type) 140 { 141 if (!type->parent_type && type->parent) { 142 type->parent_type = type_get_by_name(type->parent); 143 g_assert(type->parent_type != NULL); 144 } 145 146 return type->parent_type; 147 } 148 149 static bool type_has_parent(TypeImpl *type) 150 { 151 return (type->parent != NULL); 152 } 153 154 static size_t type_class_get_size(TypeImpl *ti) 155 { 156 if (ti->class_size) { 157 return ti->class_size; 158 } 159 160 if (type_has_parent(ti)) { 161 return type_class_get_size(type_get_parent(ti)); 162 } 163 164 return sizeof(ObjectClass); 165 } 166 167 static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) 168 { 169 TypeInfo info = { 170 .instance_size = sizeof(Interface), 171 .parent = iface->parent, 172 .class_size = sizeof(InterfaceClass), 173 .class_init = iface->interface_initfn, 174 .abstract = true, 175 }; 176 char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent); 177 178 info.name = name; 179 iface->type = type_register(&info); 180 g_free(name); 181 } 182 183 static void type_class_init(TypeImpl *ti) 184 { 185 size_t class_size = sizeof(ObjectClass); 186 int i; 187 188 if (ti->class) { 189 return; 190 } 191 192 ti->class_size = type_class_get_size(ti); 193 194 ti->class = g_malloc0(ti->class_size); 195 ti->class->type = ti; 196 197 if (type_has_parent(ti)) { 198 TypeImpl *parent = type_get_parent(ti); 199 200 type_class_init(parent); 201 202 class_size = parent->class_size; 203 g_assert(parent->class_size <= ti->class_size); 204 205 memcpy((void *)ti->class + sizeof(ObjectClass), 206 (void *)parent->class + sizeof(ObjectClass), 207 parent->class_size - sizeof(ObjectClass)); 208 } 209 210 memset((void *)ti->class + class_size, 0, ti->class_size - class_size); 211 212 for (i = 0; i < ti->num_interfaces; i++) { 213 type_class_interface_init(ti, &ti->interfaces[i]); 214 } 215 216 if (ti->class_init) { 217 ti->class_init(ti->class, ti->class_data); 218 } 219 } 220 221 static void object_interface_init(Object *obj, InterfaceImpl *iface) 222 { 223 TypeImpl *ti = iface->type; 224 Interface *iface_obj; 225 226 iface_obj = INTERFACE(object_new(ti->name)); 227 iface_obj->obj = obj; 228 229 obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj); 230 } 231 232 static void object_init_with_type(Object *obj, TypeImpl *ti) 233 { 234 int i; 235 236 if (type_has_parent(ti)) { 237 object_init_with_type(obj, type_get_parent(ti)); 238 } 239 240 for (i = 0; i < ti->num_interfaces; i++) { 241 object_interface_init(obj, &ti->interfaces[i]); 242 } 243 244 if (ti->instance_init) { 245 ti->instance_init(obj); 246 } 247 } 248 249 void object_initialize_with_type(void *data, TypeImpl *type) 250 { 251 Object *obj = data; 252 253 g_assert(type != NULL); 254 g_assert(type->instance_size >= sizeof(ObjectClass)); 255 256 type_class_init(type); 257 g_assert(type->abstract == false); 258 259 memset(obj, 0, type->instance_size); 260 obj->class = type->class; 261 object_init_with_type(obj, type); 262 } 263 264 void object_initialize(void *data, const char *typename) 265 { 266 TypeImpl *type = type_get_by_name(typename); 267 268 object_initialize_with_type(data, type); 269 } 270 271 static void object_deinit(Object *obj, TypeImpl *type) 272 { 273 if (type->instance_finalize) { 274 type->instance_finalize(obj); 275 } 276 277 while (obj->interfaces) { 278 Interface *iface_obj = obj->interfaces->data; 279 obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces); 280 object_delete(OBJECT(iface_obj)); 281 } 282 283 if (type_has_parent(type)) { 284 object_deinit(obj, type_get_parent(type)); 285 } 286 } 287 288 void object_finalize(void *data) 289 { 290 Object *obj = data; 291 TypeImpl *ti = obj->class->type; 292 293 object_deinit(obj, ti); 294 } 295 296 Object *object_new_with_type(Type type) 297 { 298 Object *obj; 299 300 g_assert(type != NULL); 301 302 obj = g_malloc(type->instance_size); 303 object_initialize_with_type(obj, type); 304 305 return obj; 306 } 307 308 Object *object_new(const char *typename) 309 { 310 TypeImpl *ti = type_get_by_name(typename); 311 312 return object_new_with_type(ti); 313 } 314 315 void object_delete(Object *obj) 316 { 317 object_finalize(obj); 318 g_free(obj); 319 } 320 321 static bool object_is_type(Object *obj, const char *typename) 322 { 323 TypeImpl *target_type = type_get_by_name(typename); 324 TypeImpl *type = obj->class->type; 325 GSList *i; 326 327 /* Check if typename is a direct ancestor of type */ 328 while (type) { 329 if (type == target_type) { 330 return true; 331 } 332 333 type = type_get_parent(type); 334 } 335 336 /* Check if obj has an interface of typename */ 337 for (i = obj->interfaces; i; i = i->next) { 338 Interface *iface = i->data; 339 340 if (object_is_type(OBJECT(iface), typename)) { 341 return true; 342 } 343 } 344 345 return false; 346 } 347 348 Object *object_dynamic_cast(Object *obj, const char *typename) 349 { 350 GSList *i; 351 352 /* Check if typename is a direct ancestor */ 353 if (object_is_type(obj, typename)) { 354 return obj; 355 } 356 357 /* Check if obj has an interface of typename */ 358 for (i = obj->interfaces; i; i = i->next) { 359 Interface *iface = i->data; 360 361 if (object_is_type(OBJECT(iface), typename)) { 362 return OBJECT(iface); 363 } 364 } 365 366 /* Check if obj is an interface and its containing object is a direct 367 * ancestor of typename */ 368 if (object_is_type(obj, TYPE_INTERFACE)) { 369 Interface *iface = INTERFACE(obj); 370 371 if (object_is_type(iface->obj, typename)) { 372 return iface->obj; 373 } 374 } 375 376 return NULL; 377 } 378 379 380 static void register_interface(void) 381 { 382 static TypeInfo interface_info = { 383 .name = TYPE_INTERFACE, 384 .instance_size = sizeof(Interface), 385 .abstract = true, 386 }; 387 388 type_register_static(&interface_info); 389 } 390 391 device_init(register_interface); 392 393 Object *object_dynamic_cast_assert(Object *obj, const char *typename) 394 { 395 Object *inst; 396 397 inst = object_dynamic_cast(obj, typename); 398 399 if (!inst) { 400 fprintf(stderr, "Object %p is not an instance of type %s\n", 401 obj, typename); 402 abort(); 403 } 404 405 return inst; 406 } 407 408 ObjectClass *object_class_dynamic_cast(ObjectClass *class, 409 const char *typename) 410 { 411 TypeImpl *target_type = type_get_by_name(typename); 412 TypeImpl *type = class->type; 413 414 while (type) { 415 if (type == target_type) { 416 return class; 417 } 418 419 type = type_get_parent(type); 420 } 421 422 return NULL; 423 } 424 425 ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, 426 const char *typename) 427 { 428 ObjectClass *ret = object_class_dynamic_cast(class, typename); 429 430 if (!ret) { 431 fprintf(stderr, "Object %p is not an instance of type %s\n", 432 class, typename); 433 abort(); 434 } 435 436 return ret; 437 } 438 439 const char *object_get_typename(Object *obj) 440 { 441 return obj->class->type->name; 442 } 443 444 ObjectClass *object_get_class(Object *obj) 445 { 446 return obj->class; 447 } 448 449 const char *object_class_get_name(ObjectClass *klass) 450 { 451 return klass->type->name; 452 } 453 454 ObjectClass *object_class_by_name(const char *typename) 455 { 456 TypeImpl *type = type_get_by_name(typename); 457 458 if (!type) { 459 return NULL; 460 } 461 462 type_class_init(type); 463 464 return type->class; 465 } 466 467 typedef struct OCFData 468 { 469 void (*fn)(ObjectClass *klass, void *opaque); 470 void *opaque; 471 } OCFData; 472 473 static void object_class_foreach_tramp(gpointer key, gpointer value, 474 gpointer opaque) 475 { 476 OCFData *data = opaque; 477 TypeImpl *type = value; 478 479 type_class_init(type); 480 481 data->fn(value, type->class); 482 } 483 484 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 485 void *opaque) 486 { 487 OCFData data = { fn, opaque }; 488 489 g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); 490 } 491