HPCToolkit
BalancedTree.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // Balanced Trees (Red-black) in the style of CLR
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 // Author:
59 // Based on code by Nathan Froyd.
60 // Nathan Tallent, Rice University.
61 //
62 //***************************************************************************
63 
64 //************************* System Include Files ****************************
65 
66 //*************************** User Include Files ****************************
67 
68 #include "BalancedTree.h"
69 
70 
71 //*************************** Forward Declarations **************************
72 
73 static void
75 
76 static void
78 
79 //***************************************************************************
80 //
81 //***************************************************************************
82 
83 
84 void
86  void* key, BalancedTreeNode_t* parent)
87 {
88  x->left = NULL;
89  x->right = NULL;
90  x->parent = parent;
92 
93  x->key = key;
94  // x->data -- client's responsibility
95 }
96 
97 
98 //***************************************************************************
99 //
100 //***************************************************************************
101 
102 void
104  BalancedTree_alloc_fn_t allocFn, size_t nodeDataSz)
105 {
106  tree->root = NULL;
107  tree->size = 0;
108 
109  tree->allocFn = allocFn;
110  tree->nodeDataSz = nodeDataSz;
111 
112  pfq_rwlock_init(&tree->rwlock);
113  spinlock_unlock(&tree->spinlock);
114 }
115 
116 
119 {
120  pfq_rwlock_node_t locklcl;
121  pfq_rwlock_write_lock(&tree->rwlock, &locklcl);
122 
123  BalancedTreeNode_t* x = tree->root;
124  BalancedTreeNode_t* x_parent = NULL;
125 
126  // ------------------------------------------------------------
127  // find existing node or new location
128  // ------------------------------------------------------------
129 
130  while (x != NULL && x->key != key) {
131  x_parent = x;
132  if (key < x->key)
133  x = x->left;
134  else
135  x = x->right;
136  }
138  if (x != NULL)
139  found = x;
140  else {
141  found = x =
143  BalancedTreeNode_init(x, key, x_parent);
144  tree->size++;
145  // ------------------------------------------------------------
146  // empty tree
147  // ------------------------------------------------------------
148  if (!tree->root)
149  tree->root = x;
150 
151 
152  // ------------------------------------------------------------
153  // rebalance
154  // ------------------------------------------------------------
155 
156  while (x != tree->root && x->parent->color == BalancedTreeColor_RED) {
157 
158  x_parent = x->parent;
159  BalancedTreeNode_t* x_gparent = x_gparent = x_parent->parent;
160 
161  if (x_parent == x_gparent->left) {
162  BalancedTreeNode_t* y = x_gparent->right;
163  if (y && y->color == BalancedTreeColor_RED) {
164  x_parent->color = BalancedTreeColor_BLACK;
166  x_gparent->color = BalancedTreeColor_RED;
167  x = x_gparent;
168  }
169  else {
170  if (x == x_parent->right) {
171  x = x_parent;
172  BalancedTree_leftRotate(tree, x);
173  x_parent = x->parent;
174  x_gparent = x_parent->parent;
175  }
176  x_parent->color = BalancedTreeColor_BLACK;
177  x_gparent->color = BalancedTreeColor_RED;
178  BalancedTree_rightRotate(tree, x_gparent);
179  }
180  }
181  else {
182  BalancedTreeNode_t* y = x_gparent->left;
183  if (y && y->color == BalancedTreeColor_RED) {
184  x_parent->color = BalancedTreeColor_BLACK;
186  x_gparent->color = BalancedTreeColor_RED;
187  x = x_gparent;
188  }
189  else {
190  if (x == x_parent->left) {
191  x = x_parent;
192  BalancedTree_rightRotate(tree, x);
193  x_parent = x->parent;
194  x_gparent = x_parent->parent;
195  }
196  x_parent->color = BalancedTreeColor_BLACK;
197  x_gparent->color = BalancedTreeColor_RED;
198  BalancedTree_leftRotate(tree, x_gparent);
199  }
200  }
201  }
202 
204  }
205 
206  pfq_rwlock_write_unlock(&tree->rwlock, &locklcl);
207  return found;
208 }
209 
210 
211 // y x |
212 // / \ / \ |
213 // x c <== a y |
214 // / \ / \ |
215 // a b b c |
216 static void
218 {
219  // set y (INVARIANT: y != NULL)
220  BalancedTreeNode_t* y = x->right;
221 
222  // move b to x's right subtree
223  x->right = y->left;
224  if (y->left != NULL) {
225  y->left->parent = x;
226  }
227 
228  // move y to x's old position
229  y->parent = x->parent;
230  if (x->parent == NULL) {
231  tree->root = y;
232  }
233  else {
234  if (x == x->parent->left) {
235  x->parent->left = y;
236  }
237  else {
238  x->parent->right = y;
239  }
240  }
241 
242  // move x to y's left
243  y->left = x;
244  x->parent = y;
245 }
246 
247 
248 // y x |
249 // / \ / \ |
250 // x c ==> a y |
251 // / \ / \ |
252 // a b b c |
253 static void
255 {
256  // set x (INVARIANT: x != NULL)
257  BalancedTreeNode_t* x = y->left;
258 
259  // move b to y's left subtree
260  y->left = x->right;
261  if (x->right != NULL) {
262  x->right->parent = y;
263  }
264 
265  // move x to y's old position
266  x->parent = y->parent;
267  if (y->parent == NULL) {
268  tree->root = x;
269  }
270  else {
271  if (y == y->parent->left) {
272  y->parent->left = x;
273  }
274  else {
275  y->parent->right = x;
276  }
277  }
278 
279  // move y to x's left
280  x->right = y;
281  y->parent = x;
282 }
283 
284 
285 #if 0
286 static void
287 BalancedTree_foreach_rec(BalancedTreeNode_t*,
288  BalancedTree_foreach_func, void*);
289 
290 void
291 BalancedTree_foreach(BalancedTree_t* tree,
292  BalancedTree_foreach_func func, void* data)
293 {
294  BalancedTree_foreach_rec(tree->root, func, data);
295 }
296 
297 
298 static void
299 BalancedTree_foreach_rec(BalancedTreeNode_t* node,
300  BalancedTree_foreach_func func, void* data)
301 {
302  if (node != NULL) {
303  BalancedTree_foreach_rec(node->left, func, data);
304 
305  func(node, data);
306 
307  BalancedTree_foreach_rec(node->right, func, data);
308  }
309 }
310 #endif
spinlock_t spinlock
Definition: BalancedTree.h:141
static BalancedTreeNode_t * BalancedTreeNode_alloc(BalancedTree_alloc_fn_t alloc, size_t dataSz)
Definition: BalancedTree.h:115
static void spinlock_unlock(spinlock_t *l)
Definition: spinlock.h:96
struct BalancedTreeNode * parent
Definition: BalancedTree.h:101
void *(* BalancedTree_alloc_fn_t)(size_t)
Definition: BalancedTree.h:88
cct_node_t * node
Definition: cct.c:128
BalancedTree_alloc_fn_t allocFn
Definition: BalancedTree.h:137
pfq_rwlock_t rwlock
Definition: BalancedTree.h:140
struct BalancedTreeNode * right
Definition: BalancedTree.h:103
void pfq_rwlock_init(pfq_rwlock_t *l)
Definition: pfq-rwlock.c:110
void BalancedTreeNode_init(BalancedTreeNode_t *x, void *key, BalancedTreeNode_t *parent)
Definition: BalancedTree.c:85
size_t nodeDataSz
Definition: BalancedTree.h:138
static void BalancedTree_rightRotate(BalancedTree_t *tree, BalancedTreeNode_t *y)
Definition: BalancedTree.c:254
struct BalancedTreeNode * left
Definition: BalancedTree.h:102
void pfq_rwlock_write_lock(pfq_rwlock_t *l, pfq_rwlock_node_t *me)
Definition: pfq-rwlock.c:149
BalancedTreeNode_t * BalancedTree_insert(BalancedTree_t *tree, void *key)
Definition: BalancedTree.c:118
void pfq_rwlock_write_unlock(pfq_rwlock_t *l, pfq_rwlock_node_t *me)
Definition: pfq-rwlock.c:211
bool found
Definition: cct.c:129
static void BalancedTree_leftRotate(BalancedTree_t *tree, BalancedTreeNode_t *x)
Definition: BalancedTree.c:217
#define NULL
Definition: ElfHelper.cpp:85
void BalancedTree_init(BalancedTree_t *tree, BalancedTree_alloc_fn_t allocFn, size_t nodeDataSz)
Definition: BalancedTree.c:103
BalancedTreeNode_t * root
Definition: BalancedTree.h:134
bitree_uwi_t * tree
BalancedTreeColor_t color
Definition: BalancedTree.h:104