Skip to content
Snippets Groups Projects
Commit 86c19c32 authored by Vladimir Davydov's avatar Vladimir Davydov Committed by Konstantin Osipov
Browse files

Replace stailq_splice with stailq_cut_tail

stailq_splice(head1, item, head2) moves elements from list 'head1'
starting from 'item' to list 'head2'. To follow the protocol, it needs
to know the element previous to 'item' in 'head1' so as to make it the
new last element of 'head1'. To achieve that, it has to loop over
'head1', which is inefficient. Actually, wherever we use this function,
we know in advance the element stailq_splice() has to look up, but we
still pass the next one, making its life difficult and obscuring the
code at the caller's side.

For example, look at how stailq_splice() is used in txn.c:

        if (stmt == NULL) {
                rollback_stmts = txn->stmts;
                stailq_create(&txn->stmts);
        } else {
                stailq_create(&rollback_stmts);
                stmt = stailq_next_entry(stmt, next);
                stailq_splice(&txn->stmts, &stmt->next, &rollback_stmts);
        }

while under the hood stailq_splice() has the loop to find 'stmt':

        stailq_splice(struct stailq *head1, struct stailq_entry *elem,
                      struct stailq *head2)
        {
                if (elem) {
                        *head2->last = elem;
                        head2->last = head1->last;
                        head1->last = &head1->first;
                        while (*head1->last != elem)
                                head1->last = &(*head1->last)->next;
                        *head1->last = NULL;
                }
        }

This is utterly preposterous.

Let's replace stailq_splice() with a new method with the same signature,
but with a slightly different semantics: move all elements from list
'head1' starting from the element *following* 'item' to list 'head2'; if
'item' is NULL, move all elements from 'head1' to 'head2'. This greatly
simplifies the code for both parties, as the callee doesn't have to loop
any more while the caller doesn't have to handle the case when 'item' is
NULL.

Also, let's change the name of this function, because stailq_splice()
sounds kinda confusing: after all, this function tears a list in two
first and only then splices the tail with another list. Let's remove the
'splice' part altogether (anyway, there's another function for splicing
lists - stailq_concat()) and call it stailq_cut_tail().
parent 2634306f
No related branches found
No related tags found
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment