RFR: 8349211: Add support for intrusive trees to the utilities red-black tree

Johan Sjölen jsjolen at openjdk.org
Mon Feb 3 20:54:17 UTC 2025


On Mon, 3 Feb 2025 11:20:49 GMT, Casper Norrbin <cnorrbin at openjdk.org> wrote:

> Hi everyone,
> 
> The recently integrated red-black tree can be made more flexible by adding support of intrusive trees. In an intrusive tree, the user has full control over node allocation and placement instead of having the tree manage it internally.
> 
> Two key changes enable this feature:
> 1. Nodes can now be created outside of the tree's internal allocation mechanism, enabling users to allocate and prepare nodes before inserting them into the tree.
> 2. Cursors have been added to simplify navigation and iteration over the tree. These cursors are when inserting and removing nodes in an intrusive tree, where the internal tree allocator is not used. Additionally, cursors enable iteration over the tree and provide a convenient way to access node values.
> 
> 
> Many of the auxiliary tree functions have been updated to use these new features, resulting in simplified and cleaned-up code. More tests have also been added to cover both new and existing functionality.
> 
> An example of how you could use the intrusive tree is found below:
> 
> ```c++
>     struct MyIntrusiveStructure {
>       Node node; // The tree node is part of an external structure
>       int data;
> 
>       MyIntrusiveStructure(int data, Node node) : node(node), data(data) {}
>       Node* get_node() { return &node; }
>       static MyIntrusiveStructure* cast_to_self(Node* node) { return (MyIntrusiveStructure*)node; }
>     };
> 
>     Tree my_intrusive_tree;
> 
>     Cursor insert_cursor = my_intrusive_tree.cursor_find(0);
>     Node insert_node = Node(0);
> 
>     // Custom allocation here is just malloc
>     MyIntrusiveStructure* place = (MyIntrusiveStructure*)os::malloc(sizeof(MyIntrusiveStructure), mtTest);
>     new (place) MyIntrusiveStructure(0, insert_node);
> 
>     my_intrusive_tree.insert_at_cursor(place->get_node(), insert_cursor);
> 
>     Cursor find_cursor = my_intrusive_tree.cursor_find(0);
>     int found_data = MyIntrusiveStructure::cast_to_self(find_cursor.node())->data;
> 
> 
> 
> Please let me know any feedback or concerns!

Thanks,

A few comments. Still looking at this.

src/hotspot/share/utilities/rbTree.hpp line 33:

> 31: #include <type_traits>
> 32: 
> 33: struct Empty {};

This will export the name `Empty` to everyone, is it possible to move it to inside of the class?

src/hotspot/share/utilities/rbTree.hpp line 71:

> 69:     const K& key() const { return _key; }
> 70:     V& val() { return _value; }
> 71:     V& val() const { return _value; }

Hmm, this doesn't seem quite right. Why can't we have a `const` method returning a `const`  value anymore?

test/hotspot/gtest/utilities/test_rbtree.cpp line 751:

> 749:   }
> 750:   { // Make a very large tree and verify at the end
> 751:   struct Nothing {};

Now can use `Empty` instead.

-------------

PR Review: https://git.openjdk.org/jdk/pull/23416#pullrequestreview-2590838361
PR Review Comment: https://git.openjdk.org/jdk/pull/23416#discussion_r1939927105
PR Review Comment: https://git.openjdk.org/jdk/pull/23416#discussion_r1939928307
PR Review Comment: https://git.openjdk.org/jdk/pull/23416#discussion_r1940006437


More information about the hotspot-dev mailing list