• E
    qapi: Simplify semantics of visit_next_list() · d9f62dde
    Eric Blake 提交于
    The semantics of the list visit are somewhat baroque, with the
    following pseudocode when FooList is used:
    
    start()
    for (prev = head; cur = next(prev); prev = &cur) {
        visit(&cur->value)
    }
    
    Note that these semantics (advance before visit) requires that
    the first call to next() return the list head, while all other
    calls return the next element of the list; that is, every visitor
    implementation is required to track extra state to decide whether
    to return the input as-is, or to advance.  It also requires an
    argument of 'GenericList **' to next(), solely because the first
    iteration might need to modify the caller's GenericList head, so
    that all other calls have to do a layer of dereferencing.
    
    Thankfully, we only have two uses of list visits in the entire
    code base: one in spapr_drc (which completely avoids
    visit_next_list(), feeding in integers from a different source
    than uint8List), and one in qapi-visit.py.  That is, all other
    list visitors are generated in qapi-visit.c, and share the same
    paradigm based on a qapi FooList type, so we can refactor how
    lists are laid out with minimal churn among clients.
    
    We can greatly simplify things by hoisting the special case
    into the start() routine, and flipping the order in the loop
    to visit before advance:
    
    start(head)
    for (tail = *head; tail; tail = next(tail)) {
        visit(&tail->value)
    }
    
    With the simpler semantics, visitors have less state to track,
    the argument to next() is reduced to 'GenericList *', and it
    also becomes obvious whether an input visitor is allocating a
    FooList during visit_start_list() (rather than the old way of
    not knowing if an allocation happened until the first
    visit_next_list()).  As a minor drawback, we now allocate in
    two functions instead of one, and have to pass the size to
    both functions (unless we were to tweak the input visitors to
    cache the size to start_list for reuse during next_list, but
    that defeats the goal of less visitor state).
    
    The signature of visit_start_list() is chosen to match
    visit_start_struct(), with the new parameters after 'name'.
    
    The spapr_drc case is a virtual visit, done by passing NULL for
    list, similarly to how NULL is passed to visit_start_struct()
    when a qapi type is not used in those visits.  It was easy to
    provide these semantics for qmp-output and dealloc visitors,
    and a bit harder for qmp-input (several prerequisite patches
    refactored things to make this patch straightforward).  But it
    turned out that the string and opts visitors munge enough other
    state during visit_next_list() to make it easier to just
    document and require a GenericList visit for now; an assertion
    will remind us to adjust things if we need the semantics in the
    future.
    
    Several pre-requisite cleanup patches made the reshuffling of
    the various visitors easier; particularly the qmp input visitor.
    Signed-off-by: NEric Blake <eblake@redhat.com>
    Message-Id: <1461879932-9020-24-git-send-email-eblake@redhat.com>
    Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
    d9f62dde
spapr_drc.c 28.4 KB