[PATCH 1/2] rbtree.h: Store parent in each entry and use that to manipulate the tree without a stack.

Jacek Caban jacek at codeweavers.com
Mon Aug 15 14:57:00 CDT 2016


Hi Henri,


On 8/11/16 2:50 PM, Henri Verbeet wrote:
> On 10 August 2016 at 16:01, Jacek Caban <jacek at codeweavers.com> wrote:
>>   include/wine/rbtree.h | 376
>> +++++++++++++++++++++++++++-----------------------
>>   1 file changed, 200 insertions(+), 176 deletions(-)
>>
> Since this patch was assigned to me...
>
> I think this patch has quite a number of unrelated changes,

Implementation details that I change in helper functions affect other 
parts in such a way, that one patch felt appropriate. Anyway, I sent a 
split version (at the cost of temporary arguments).

> to the point that the patch touches over half of the lines in the file

Yes, that's more or less a rewrite, so it's not surprising.

> and I think deletion for example ends up just being a different algorithm.

Yes, that's intentional and there are reasons for that. The algorithm 
that I used (see implementation from Introduction to Algorithms book for 
reference) needs only bottom-up traversal once you have the node, which 
is perfect for following parent chain. Instead of doing rotations on way 
down and up, we do them just when going up. And, although asymptotically 
it's the same complexity, it usually needs fewer steps since it stops at 
the first red parent. Further, the traversal down can be a simple 
wine_rb_get call (and I intend to change it further so that 
wine_rb_remove takes wine_rb_entry as an argument, but that's something 
for future discussion). All that wasn't possible when we had to record 
the path to root on the stack, but when I had to make significant 
changes to the function anyway, I think that's a good moment to do full 
rewrite and take those little advantages.

> And while the aforementioned means I didn't look at everything in
> quite the amount of detail that would otherwise be appropriate, I do
> think some of those changes make things overly complicated. For
> example, a straightforward modification to wine_rb_put() would turn it
> into something like the following:
>
>
>      static inline int wine_rb_put(struct wine_rb_tree *tree, const
> void *key, struct wine_rb_entry *entry)
>      {
>         struct wine_rb_entry **node = &tree->root;
>         struct wine_rb_entry *parent = *node;
>
>         while (*node)
>         {
>             int c;
>
>             if (!(c = tree->functions->compare(key, *node)))
>                 return -1;
>             parent = *node;
>             if (c < 0) node = &(*node)->left;
>             else node = &(*node)->right;
>         }
>
>         entry->flags = WINE_RB_FLAG_RED;
>         entry->parent = parent;
>         entry->left = NULL;
>         entry->right = NULL;
>         *node = entry;
>
>         wine_rb_fixup(&tree->root, entry);
>         tree->root->flags &= ~WINE_RB_FLAG_RED;
>
>         return 0;
>      }
>
>
> I think that's much clearer than what this patch does with wine_rb_put().

Well, I don't see why one or another is cleaner, but it indeed slightly 
reduces the diff, so I changed that.

Thanks,
Jacek



More information about the wine-devel mailing list