Skip to content

Commit e197f6f

Browse files
committed
[libc++] Document how __tree is layed out and how we iterate through it
1 parent 3b10b9a commit e197f6f

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

libcxx/include/__tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@
4747
_LIBCPP_PUSH_MACROS
4848
#include <__undef_macros>
4949

50+
// __tree is a red-black-tree implementation used for the associative containers (i.e. (multi)map/set). It stores
51+
// - (1) a pointer to the node with the smallest (i.e. leftmost) element, namely __begin_node_
52+
// - (2) the number of nodes in the tree, namely __size_
53+
// - (3) a pointer to the root of the tree, namely __end_node_
54+
//
55+
// Storing (1) and (2) is required to allow for constant time lookups. A tree looks like this in memory:
56+
//
57+
// __end_node_
58+
// |
59+
// root
60+
// / \
61+
// l1 r1
62+
// / \ / \
63+
// ... ... ... ...
64+
//
65+
// All nodes except __end_node_ have a __left_ and __right_ pointer as well as a __parent_ pointer.
66+
// __end_node_ only contains a __left_ pointer, which points to the root of the tree.
67+
// This layout allows for iteration through the tree without a need for special handling of the end node. See
68+
// __tree_next_iter and __tree_prev_iter for more details.
69+
5070
_LIBCPP_BEGIN_NAMESPACE_STD
5171

5272
template <class _Pointer>
@@ -167,6 +187,11 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT {
167187
return __x->__parent_unsafe();
168188
}
169189

190+
// __tree_next_iter and __tree_prev_iter implement iteration through the tree. The order is as follows:
191+
// left sub-tree -> node -> right sub-tree. When the right-most node of a sub-tree is reached, we walk up the tree until
192+
// we find a node where we were in the left sub-tree. We are _always_ in a left sub-tree, since the __end_node_ points
193+
// to the actual root of the tree through a __left_ pointer. Incrementing the end() pointer is UB, so we can assume that
194+
// never happens.
170195
template <class _EndNodePtr, class _NodePtr>
171196
inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT {
172197
_LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");

0 commit comments

Comments
 (0)