diff --git a/msvc/unicorn/qapi-types.c b/msvc/unicorn/qapi-types.c index ddaa3758..b02571d4 100644 --- a/msvc/unicorn/qapi-types.c +++ b/msvc/unicorn/qapi-types.c @@ -20,17 +20,15 @@ void qapi_free_DummyForceArrays(DummyForceArrays *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_DummyForceArrays(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } const char *const QType_lookup[] = { @@ -57,32 +55,28 @@ const char *const QapiErrorClass_lookup[] = { void qapi_free_X86CPUFeatureWordInfo(X86CPUFeatureWordInfo *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_X86CPUFeatureWordInfo(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_X86CPUFeatureWordInfoList(X86CPUFeatureWordInfoList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_X86CPUFeatureWordInfoList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } const char *const X86CPURegister32_lookup[] = { @@ -99,210 +93,182 @@ const char *const X86CPURegister32_lookup[] = { void qapi_free_anyList(anyList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_anyList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_boolList(boolList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_boolList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_int16List(int16List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_int16List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_int32List(int32List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_int32List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_int64List(int64List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_int64List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_int8List(int8List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_int8List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_intList(intList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_intList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_numberList(numberList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_numberList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_sizeList(sizeList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_sizeList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_strList(strList *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_strList(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_uint16List(uint16List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_uint16List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_uint32List(uint32List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_uint32List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_uint64List(uint64List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_uint64List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } void qapi_free_uint8List(uint8List *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_uint8List(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } diff --git a/qemu/include/qapi/dealloc-visitor.h b/qemu/include/qapi/dealloc-visitor.h index 45b06b24..b3e5c85f 100644 --- a/qemu/include/qapi/dealloc-visitor.h +++ b/qemu/include/qapi/dealloc-visitor.h @@ -23,9 +23,6 @@ typedef struct QapiDeallocVisitor QapiDeallocVisitor; * qapi_free_FOO() functions, and is the only visitor designed to work * correctly in the face of a partially-constructed QAPI tree. */ -QapiDeallocVisitor *qapi_dealloc_visitor_new(void); -void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d); - -Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v); +Visitor *qapi_dealloc_visitor_new(void); #endif diff --git a/qemu/include/qapi/visitor-impl.h b/qemu/include/qapi/visitor-impl.h index 2e185b84..9e74519b 100644 --- a/qemu/include/qapi/visitor-impl.h +++ b/qemu/include/qapi/visitor-impl.h @@ -105,6 +105,9 @@ struct Visitor /* Must be set */ VisitorType type; + + /* Must be set */ + void (*free)(Visitor *v); }; #endif diff --git a/qemu/include/qapi/visitor.h b/qemu/include/qapi/visitor.h index 564f4063..717e9d10 100644 --- a/qemu/include/qapi/visitor.h +++ b/qemu/include/qapi/visitor.h @@ -39,6 +39,24 @@ * implemented by each visitor, and docs/qapi-code-gen.txt for more * about the QAPI code generator. * + * All of the visitors are created via: + * + * Type *subtype_visitor_new(parameters...); + * + * where Type is either directly 'Visitor *', or is a subtype that can + * be trivially upcast to Visitor * via another function: + * + * Visitor *subtype_get_visitor(SubtypeVisitor *); + * + * A visitor should be used for exactly one top-level visit_type_FOO() + * or virtual walk, then passed to visit_free() to clean up resources. + * It is okay to free the visitor without completing the visit, if + * some other error is detected in the meantime. Output visitors + * provide an additional function, for collecting the final results of + * a successful visit: string_output_get_string() and + * qmp_output_get_qobject(); this collection function should not be + * called if any errors were reported during the visit. + * * All QAPI types have a corresponding function with a signature * roughly compatible with this: * @@ -225,6 +243,18 @@ typedef struct GenericAlternate { char padding[]; } GenericAlternate; +/*** Visitor cleanup ***/ + +/* + * Free @v and any resources it has tied up. + * + * May be called whether or not the visit has been successfully + * completed, but should not be called until a top-level + * visit_type_FOO() or visit_start_ITEM() has been performed on the + * visitor. Safe if @v is NULL. + */ +void visit_free(Visitor *v); + /*** Visiting structures ***/ @@ -276,7 +306,7 @@ void visit_check_struct(Visitor *v, Error **errp); * Must be called after any successful use of visit_start_struct(), * even if intermediate processing was skipped due to errors, to allow * the backend to release any resources. Destroying the visitor early - * behaves as if this was implicitly called. + * with visit_free() behaves as if this was implicitly called. */ void visit_end_struct(Visitor *v, void **obj); @@ -341,7 +371,7 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size); * Must be called after any successful use of visit_start_list(), even * if intermediate processing was skipped due to errors, to allow the * backend to release any resources. Destroying the visitor early - * behaves as if this was implicitly called. + * with visit_free() behaves as if this was implicitly called. */ void visit_end_list(Visitor *v, void **list); @@ -374,7 +404,7 @@ void visit_start_alternate(Visitor *v, const char *name, * Must be called after any successful use of visit_start_alternate(), * even if intermediate processing was skipped due to errors, to allow * the backend to release any resources. Destroying the visitor early - * behaves as if this was implicitly called. + * with visit_free() behaves as if this was implicitly called. */ void visit_end_alternate(Visitor *v, void **obj); diff --git a/qemu/qapi/qapi-dealloc-visitor.c b/qemu/qapi/qapi-dealloc-visitor.c index ba0ee854..3a2b94ea 100644 --- a/qemu/qapi/qapi-dealloc-visitor.c +++ b/qemu/qapi/qapi-dealloc-visitor.c @@ -104,26 +104,16 @@ static void qapi_dealloc_type_anything(Visitor *v, const char *name, } } -static void qapi_dealloc_type_size(Visitor *v, const char *name, uint64_t *obj, - Error **errp) -{ -} - static void qapi_dealloc_type_null(Visitor *v, const char *name, Error **errp) { } -Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v) +static void qapi_dealloc_free(Visitor *v) { - return &v->visitor; + g_free(container_of(v, QapiDeallocVisitor, visitor)); } -void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v) -{ - g_free(v); -} - -QapiDeallocVisitor *qapi_dealloc_visitor_new(void) +Visitor *qapi_dealloc_visitor_new(void) { QapiDeallocVisitor *v; @@ -144,7 +134,7 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v->visitor.type_number = qapi_dealloc_type_number; v->visitor.type_any = qapi_dealloc_type_anything; v->visitor.type_null = qapi_dealloc_type_null; - v->visitor.type_size = qapi_dealloc_type_size; + v->visitor.free = qapi_dealloc_free; - return v; + return &v->visitor; } diff --git a/qemu/qapi/qapi-visit-core.c b/qemu/qapi/qapi-visit-core.c index 2728b910..1c9f6458 100644 --- a/qemu/qapi/qapi-visit-core.c +++ b/qemu/qapi/qapi-visit-core.c @@ -21,6 +21,13 @@ #include "qapi/visitor.h" #include "qapi/visitor-impl.h" +void visit_free(Visitor *v) +{ + if (v) { + v->free(v); + } +} + void visit_start_struct(Visitor *v, const char *name, void **obj, size_t size, Error **errp) { diff --git a/qemu/qapi/qmp-input-visitor.c b/qemu/qapi/qmp-input-visitor.c index 67a44aa0..93dddffb 100644 --- a/qemu/qapi/qmp-input-visitor.c +++ b/qemu/qapi/qmp-input-visitor.c @@ -379,6 +379,13 @@ Visitor *qmp_input_get_visitor(QmpInputVisitor *v) return &v->visitor; } +static void qmp_input_free(Visitor *v) +{ + QmpInputVisitor *qiv = to_qiv(v); + + qmp_input_visitor_cleanup(qiv); +} + void qmp_input_visitor_cleanup(QmpInputVisitor *v) { qobject_decref(v->root); @@ -407,6 +414,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj, bool strict) v->visitor.type_any = qmp_input_type_any; v->visitor.type_null = qmp_input_type_null; v->visitor.optional = qmp_input_optional; + v->visitor.free = qmp_input_free; v->strict = strict; v->root = obj; diff --git a/qemu/qapi/qmp-output-visitor.c b/qemu/qapi/qmp-output-visitor.c index 76d76a0a..95915180 100644 --- a/qemu/qapi/qmp-output-visitor.c +++ b/qemu/qapi/qmp-output-visitor.c @@ -215,6 +215,13 @@ Visitor *qmp_output_get_visitor(QmpOutputVisitor *v) return &v->visitor; } +static void qmp_output_free(Visitor *v) +{ + QmpOutputVisitor *qov = to_qov(v); + + qmp_output_visitor_cleanup(qov); +} + void qmp_output_visitor_cleanup(QmpOutputVisitor *v) { QStackEntry *e, *tmp; @@ -247,6 +254,7 @@ QmpOutputVisitor *qmp_output_visitor_new(void) v->visitor.type_number = qmp_output_type_number; v->visitor.type_any = qmp_output_type_any; v->visitor.type_null = qmp_output_type_null; + v->visitor.free = qmp_output_free; QTAILQ_INIT(&v->stack); diff --git a/qemu/qapi/string-input-visitor.c b/qemu/qapi/string-input-visitor.c index fb514970..f7563118 100644 --- a/qemu/qapi/string-input-visitor.c +++ b/qemu/qapi/string-input-visitor.c @@ -309,6 +309,13 @@ Visitor *string_input_get_visitor(StringInputVisitor *v) return &v->visitor; } +static void string_input_free(Visitor *v) +{ + StringInputVisitor *siv = to_siv(v); + + string_input_visitor_cleanup(siv); +} + void string_input_visitor_cleanup(StringInputVisitor *v) { g_list_foreach(v->ranges, free_range, NULL); @@ -333,6 +340,7 @@ StringInputVisitor *string_input_visitor_new(const char *str) v->visitor.next_list = next_list; v->visitor.end_list = end_list; v->visitor.optional = parse_optional; + v->visitor.free = string_input_free; v->string = str; return v; diff --git a/qemu/scripts/qapi-event.py b/qemu/scripts/qapi-event.py index 64db422a..00bc3237 100644 --- a/qemu/scripts/qapi-event.py +++ b/qemu/scripts/qapi-event.py @@ -119,7 +119,7 @@ def gen_event_send(name, arg_type): if arg_type and arg_type.members: ret += mcgen(''' out: - qmp_output_visitor_cleanup(qov); + visit_free(v); ''') ret += mcgen(''' error_propagate(errp, err); diff --git a/qemu/scripts/qapi-types.py b/qemu/scripts/qapi-types.py index 7d9fb481..7fba35db 100644 --- a/qemu/scripts/qapi-types.py +++ b/qemu/scripts/qapi-types.py @@ -180,17 +180,15 @@ def gen_type_cleanup(name): void qapi_free_%(c_name)s(%(c_name)s *obj) { - QapiDeallocVisitor *qdv; Visitor *v; if (!obj) { return; } - qdv = qapi_dealloc_visitor_new(); - v = qapi_dealloc_get_visitor(qdv); + v = qapi_dealloc_visitor_new(); visit_type_%(c_name)s(v, NULL, &obj, NULL); - qapi_dealloc_visitor_cleanup(qdv); + visit_free(v); } ''', c_name=c_name(name))