Intrusive Containers
Loading...
Searching...
No Matches
BalTreeIn.hpp
Go to the documentation of this file.
1#ifndef BalTreeIn_HPP
2#define BalTreeIn_HPP
3
4/**
5@file BalTreeIn.hpp
6@brief Intrusive Binary Tree, Implementation of Balancing Primitives
7
8This file defines a pair of templates (BalTreeInRoot and BalTreeInNode) that
9implement the Balancing Primitives for an intrusive binary tree.
10A Derived class is responsible for implementing the balancing rules.
11
12@copyright (c) 2022-2024 Richard Damon
13@parblock
14MIT License:
15
16Permission is hereby granted, free of charge, to any person obtaining a copy
17of this software and associated documentation files (the "Software"), to deal
18in the Software without restriction, including without limitation the rights
19to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20copies of the Software, and to permit persons to whom the Software is
21furnished to do so, subject to the following conditions:
22
23The above copyright notice and this permission notice shall be included in
24all copies or substantial portions of the Software.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32THE SOFTWARE.
33@endparblock
34
35@see BalTreeIn.h
36@ingroup IntrusiveContainers
37*/
38
39#include "BalTreeIn.h"
40#include "TreeIn.hpp"
41
42/******************************************************************************************
43Implementation
44
45Note that when we need to convert a List or Node pointer/reference to a TreeInRoot/ListInNode
46pointer/reference we need to do an explicit static_cast, to avoid ambiguity in the case of
47classes deriving from multiple versions of TreeInRoot/ListInNode
48*/
49
50#if TREEIN_CHECK
51
52// TODO Can this just fall back to TreeIn::check()? I don't think we have anything additional to check.
53/**
54*/
55template <class R, class N, class K, ContainerThreadSafety s, int n>
56inline bool BalTreeInNode<R, N, K, s, n>::check() const {
57 N const* me = static_cast<N const*>(this);
58 unsigned save = readLock(false);
59 if (root()) {
60 Root* myroot = root();
61 if (parent() == nullptr) {
62 TREEIN_ASSERT(static_cast<Root*>(root())->m_base == me);
63 } else {
64 Node* myparent = parent();
65 TREEIN_ASSERT(myparent->left() == me || myparent->right() == me);
66 TREEIN_ASSERT(myparent->root() == root());
67 }
68
69 if (left()) {
70 Node* myleft = left();
71 TREEIN_ASSERT(myleft->m_parent == me);
72 TREEIN_ASSERT(myroot->compare(*me, *left()) <= 0);
73 TREEIN_ASSERT(myroot->compare(*left(), *me) >= 0);
74 }
75
76 if (right()) {
77 Node* myright = right();
78 TREEIN_ASSERT(myright->parent() == me);
79 TREEIN_ASSERT(myroot->compare(*me, *right()) >= 0);
80 TREEIN_ASSERT(myroot->compare(*right(), *me) <= 0);
81 }
82 } else {
83 TREEIN_ASSERT(parent() == nullptr);
84 TREEIN_ASSERT(left() == nullptr);
85 TREEIN_ASSERT(right() == nullptr);
86 }
87 readUnlock(save);
88 return true;
89}
90
91// TODO Can this just fall back to TreeInRoot::check()?
92template <class R, class N, class K, ContainerThreadSafety s, int n>
93inline bool BalTreeInRoot<R, N, K, s, n>::check() const {
94 R const* me = static_cast<R const*>(this);
95 unsigned save = readLock(false);
96 if (base()) {
97 Node* node = static_cast<Node*>(base());
98 TREEIN_ASSERT(node->root() == me);
99 TREEIN_ASSERT(node->parent() == nullptr);
100 node->check();
101 }
102 readUnlock(save);
103 return true;
104}
105#else
106template <class R, class N, class K, ContainerThreadSafety s, int n> inline bool BalTreeInNode<R, N, K, s, n>::check() const { return true; }
107template <class R, class N, class K, ContainerThreadSafety s, int n> inline bool BalTreeInRoot<R, N, K, s, n>::check() const { return true; }
108#endif
109
110/**
111Constructor.
112
113Starts us as an empty list.
114*/
115template <class R, class N, class K, ContainerThreadSafety s, int n>
118
119/**
120Destructor.
121
122
123*/
124template <class R, class N, class K, ContainerThreadSafety s, int n>
127
128/**
129Constructor.
130
131*/
132template <class R, class N, class K, ContainerThreadSafety s,int n>
136
137/**
138 * Destructor.
139*/
140template <class R, class N, class K, ContainerThreadSafety s, int n>
144#endif
145
146/**
147 * @brief Balance tree with a Left Rotate.
148 *
149 * @verbatim
150 Given A < L < B < R < C
151 Either P < A, or C < P
152 (A, B, C are subtrees, relations apply to ALL members in that subtree)
153
154 P P
155 | |
156 R Rotate Right => L
157 / \ <= Rotate Left / \
158 L C A R
159 / \ / \
160 A B B C
161
162 @endverbatim
163 *
164 * Rotate Right moves the current node to the right of the node on its left
165 * Rotate Left moves the current to to the left of the node on its right.
166 *
167 * Caller should have an upgradable read-lock
168 *
169 * Anyone walking the tree should have a readLock that we will wait to be released.
170 *
171 * @return New subtree root after rotation.
172 */
173
174template<class R, class N, class K, ContainerThreadSafety s, int n>
176 unsigned save = writeLock(true);
177 // this/root = L, pivot = R
178 N* pivot = this->Base::m_right;
179 Node* pivot_ = pivot;
180 N* me = static_cast<N*>(this);
181
182 // Move middle node (B) from Pivot to Root
183 this->Base::m_right = pivot->Base::m_left;
184 if(this->Base::m_right){
185 this->Base::m_right->Base::m_parent = me;
186 }
187
188 // Points Roots parent to Pivot
189 pivot_->Base::m_parent = this->Base::m_parent;
190 if(pivot_->Base::m_parent) { // Check if left, right or was tree root
191 if(pivot->Base::m_parent->Base::m_left == this) {
192 pivot_->Base::m_parent->Base::m_left = pivot;
193 } else {
194 pivot_->Base::m_parent->Base::m_right = pivot;
195 }
196 } else {
197 Root* root = pivot_->Base::m_root;
198 root->m_base = pivot;
199 }
200
201 // Connect Pivot to the (old) Root of the rotation.
202 pivot_->Base::m_left = me;
203 this->Base::m_parent = pivot;
204 writeUnlock(save);
205 return pivot;
206}
207
208/**
209 * @brief Balance Tree with a Right Rotate
210 *
211 * @see rotateLeft
212 *
213 * @return new subtree root after rotation.
214 */
215template<class R, class N, class K, ContainerThreadSafety s, int n>
217 unsigned save = writeLock(true);
218 //this/root = R, pivot = L
219 N* pivot = this->Base::m_left;
220 Node* pivot_ = pivot;
221 N* me = static_cast<N*>(this);
222
223 // Move middle node (B) from Pivot to Root
224 this->Base::m_left = pivot->Base::m_right;
225 if(this->Base::m_left) {
226 this->Base::m_left->Base::m_parent = me;
227 }
228
229 // Point Roots Parent to Pivot
230 pivot_->Base::m_parent = this->Base::m_parent;
231 if(pivot->Base::m_parent) { // Check if left, right or was tree root
232 if(pivot->Base::m_parent->Base::m_left == this) {
233 pivot->Base::m_parent->Base::m_left = pivot;
234 } else {
235 pivot->Base::m_parent->Base::m_right = pivot;
236 }
237 } else {
238 Root* root = pivot_->Base::m_root;
239 root->m_base = pivot;
240 }
241 // Reconnect Pivot and (old) Root of the rotation
242 pivot->Base::m_right = me;
243 this->Base::m_parent = pivot;
244 writeUnlock(save);
245
246 return pivot;
247}
Intrusive Binary Tree (balenced).
Intrusive Binary Tree (unbalenced), Implementation.
BalTreeInNode()
Constructor.
Definition BalTreeIn.hpp:133
virtual ~BalTreeInNode()
Destructor.
Definition BalTreeIn.hpp:141
N * rotateLeft()
Balance tree with a Left Rotate.
Definition BalTreeIn.hpp:175
N * rotateRight()
Balance Tree with a Right Rotate.
Definition BalTreeIn.hpp:216
class BalTreeInNode< R, N, K, s, n > Node
Type of Node.
Definition BalTreeIn.h:226
class BalTreeInRoot< R, N, K, s, n > Root
Type of Root.
Definition BalTreeIn.h:225
bool check() const override
Definition BalTreeIn.hpp:106
bool check() const override
Definition BalTreeIn.hpp:107
virtual ~BalTreeInRoot()
Destructor.
Definition BalTreeIn.hpp:125
BalTreeInRoot()
Constructor.
Definition BalTreeIn.hpp:116