• E
    qapi: Add new visit_complete() function · 3b098d56
    Eric Blake 提交于
    Making each output visitor provide its own output collection
    function was the only remaining reason for exposing visitor
    sub-types to the rest of the code base.  Add a polymorphic
    visit_complete() function which is a no-op for input visitors,
    and which populates an opaque pointer for output visitors.  For
    maximum type-safety, also add a parameter to the output visitor
    constructors with a type-correct version of the output pointer,
    and assert that the two uses match.
    
    This approach was considered superior to either passing the
    output parameter only during construction (action at a distance
    during visit_free() feels awkward) or only during visit_complete()
    (defeating type safety makes it easier to use incorrectly).
    
    Most callers were function-local, and therefore a mechanical
    conversion; the testsuite was a bit trickier, but the previous
    cleanup patch minimized the churn here.
    
    The visit_complete() function may be called at most once; doing
    so lets us use transfer semantics rather than duplication or
    ref-count semantics to get the just-built output back to the
    caller, even though it means our behavior is not idempotent.
    
    Generated code is simplified as follows for events:
    
    |@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
    |     QDict *qmp;
    |     Error *err = NULL;
    |     QMPEventFuncEmit emit;
    |-    QmpOutputVisitor *qov;
    |+    QObject *obj;
    |     Visitor *v;
    |     q_obj_ACPI_DEVICE_OST_arg param = {
    |         info
    |@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
    |
    |     qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
    |
    |-    qov = qmp_output_visitor_new();
    |-    v = qmp_output_get_visitor(qov);
    |+    v = qmp_output_visitor_new(&obj);
    |
    |     visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
    |     if (err) {
    |@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
    |         goto out;
    |     }
    |
    |-    qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
    |+    visit_complete(v, &obj);
    |+    qdict_put_obj(qmp, "data", obj);
    |     emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
    
    and for commands:
    
    | {
    |     Error *err = NULL;
    |-    QmpOutputVisitor *qov = qmp_output_visitor_new();
    |     Visitor *v;
    |
    |-    v = qmp_output_get_visitor(qov);
    |+    v = qmp_output_visitor_new(ret_out);
    |     visit_type_AddfdInfo(v, "unused", &ret_in, &err);
    |-    if (err) {
    |-        goto out;
    |+    if (!err) {
    |+        visit_complete(v, ret_out);
    |     }
    |-    *ret_out = qmp_output_get_qobject(qov);
    |-
    |-out:
    |     error_propagate(errp, err);
    Signed-off-by: NEric Blake <eblake@redhat.com>
    Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
    Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
    Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
    3b098d56
qemu-sockets.c 32.5 KB