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