Annotation of embedaddon/nginx/src/core/ngx_rbtree.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10:
11:
12: /*
13: * The red-black tree code is based on the algorithm described in
14: * the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
15: */
16:
17:
18: static ngx_inline void ngx_rbtree_left_rotate(ngx_rbtree_node_t **root,
19: ngx_rbtree_node_t *sentinel, ngx_rbtree_node_t *node);
20: static ngx_inline void ngx_rbtree_right_rotate(ngx_rbtree_node_t **root,
21: ngx_rbtree_node_t *sentinel, ngx_rbtree_node_t *node);
22:
23:
24: void
25: ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
26: ngx_rbtree_node_t *node)
27: {
28: ngx_rbtree_node_t **root, *temp, *sentinel;
29:
30: /* a binary tree insert */
31:
32: root = (ngx_rbtree_node_t **) &tree->root;
33: sentinel = tree->sentinel;
34:
35: if (*root == sentinel) {
36: node->parent = NULL;
37: node->left = sentinel;
38: node->right = sentinel;
39: ngx_rbt_black(node);
40: *root = node;
41:
42: return;
43: }
44:
45: tree->insert(*root, node, sentinel);
46:
47: /* re-balance tree */
48:
49: while (node != *root && ngx_rbt_is_red(node->parent)) {
50:
51: if (node->parent == node->parent->parent->left) {
52: temp = node->parent->parent->right;
53:
54: if (ngx_rbt_is_red(temp)) {
55: ngx_rbt_black(node->parent);
56: ngx_rbt_black(temp);
57: ngx_rbt_red(node->parent->parent);
58: node = node->parent->parent;
59:
60: } else {
61: if (node == node->parent->right) {
62: node = node->parent;
63: ngx_rbtree_left_rotate(root, sentinel, node);
64: }
65:
66: ngx_rbt_black(node->parent);
67: ngx_rbt_red(node->parent->parent);
68: ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);
69: }
70:
71: } else {
72: temp = node->parent->parent->left;
73:
74: if (ngx_rbt_is_red(temp)) {
75: ngx_rbt_black(node->parent);
76: ngx_rbt_black(temp);
77: ngx_rbt_red(node->parent->parent);
78: node = node->parent->parent;
79:
80: } else {
81: if (node == node->parent->left) {
82: node = node->parent;
83: ngx_rbtree_right_rotate(root, sentinel, node);
84: }
85:
86: ngx_rbt_black(node->parent);
87: ngx_rbt_red(node->parent->parent);
88: ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
89: }
90: }
91: }
92:
93: ngx_rbt_black(*root);
94: }
95:
96:
97: void
98: ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
99: ngx_rbtree_node_t *sentinel)
100: {
101: ngx_rbtree_node_t **p;
102:
103: for ( ;; ) {
104:
105: p = (node->key < temp->key) ? &temp->left : &temp->right;
106:
107: if (*p == sentinel) {
108: break;
109: }
110:
111: temp = *p;
112: }
113:
114: *p = node;
115: node->parent = temp;
116: node->left = sentinel;
117: node->right = sentinel;
118: ngx_rbt_red(node);
119: }
120:
121:
122: void
123: ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
124: ngx_rbtree_node_t *sentinel)
125: {
126: ngx_rbtree_node_t **p;
127:
128: for ( ;; ) {
129:
130: /*
131: * Timer values
132: * 1) are spread in small range, usually several minutes,
133: * 2) and overflow each 49 days, if milliseconds are stored in 32 bits.
134: * The comparison takes into account that overflow.
135: */
136:
137: /* node->key < temp->key */
138:
139: p = ((ngx_rbtree_key_int_t) (node->key - temp->key) < 0)
140: ? &temp->left : &temp->right;
141:
142: if (*p == sentinel) {
143: break;
144: }
145:
146: temp = *p;
147: }
148:
149: *p = node;
150: node->parent = temp;
151: node->left = sentinel;
152: node->right = sentinel;
153: ngx_rbt_red(node);
154: }
155:
156:
157: void
158: ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
159: ngx_rbtree_node_t *node)
160: {
161: ngx_uint_t red;
162: ngx_rbtree_node_t **root, *sentinel, *subst, *temp, *w;
163:
164: /* a binary tree delete */
165:
166: root = (ngx_rbtree_node_t **) &tree->root;
167: sentinel = tree->sentinel;
168:
169: if (node->left == sentinel) {
170: temp = node->right;
171: subst = node;
172:
173: } else if (node->right == sentinel) {
174: temp = node->left;
175: subst = node;
176:
177: } else {
178: subst = ngx_rbtree_min(node->right, sentinel);
179:
180: if (subst->left != sentinel) {
181: temp = subst->left;
182: } else {
183: temp = subst->right;
184: }
185: }
186:
187: if (subst == *root) {
188: *root = temp;
189: ngx_rbt_black(temp);
190:
191: /* DEBUG stuff */
192: node->left = NULL;
193: node->right = NULL;
194: node->parent = NULL;
195: node->key = 0;
196:
197: return;
198: }
199:
200: red = ngx_rbt_is_red(subst);
201:
202: if (subst == subst->parent->left) {
203: subst->parent->left = temp;
204:
205: } else {
206: subst->parent->right = temp;
207: }
208:
209: if (subst == node) {
210:
211: temp->parent = subst->parent;
212:
213: } else {
214:
215: if (subst->parent == node) {
216: temp->parent = subst;
217:
218: } else {
219: temp->parent = subst->parent;
220: }
221:
222: subst->left = node->left;
223: subst->right = node->right;
224: subst->parent = node->parent;
225: ngx_rbt_copy_color(subst, node);
226:
227: if (node == *root) {
228: *root = subst;
229:
230: } else {
231: if (node == node->parent->left) {
232: node->parent->left = subst;
233: } else {
234: node->parent->right = subst;
235: }
236: }
237:
238: if (subst->left != sentinel) {
239: subst->left->parent = subst;
240: }
241:
242: if (subst->right != sentinel) {
243: subst->right->parent = subst;
244: }
245: }
246:
247: /* DEBUG stuff */
248: node->left = NULL;
249: node->right = NULL;
250: node->parent = NULL;
251: node->key = 0;
252:
253: if (red) {
254: return;
255: }
256:
257: /* a delete fixup */
258:
259: while (temp != *root && ngx_rbt_is_black(temp)) {
260:
261: if (temp == temp->parent->left) {
262: w = temp->parent->right;
263:
264: if (ngx_rbt_is_red(w)) {
265: ngx_rbt_black(w);
266: ngx_rbt_red(temp->parent);
267: ngx_rbtree_left_rotate(root, sentinel, temp->parent);
268: w = temp->parent->right;
269: }
270:
271: if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
272: ngx_rbt_red(w);
273: temp = temp->parent;
274:
275: } else {
276: if (ngx_rbt_is_black(w->right)) {
277: ngx_rbt_black(w->left);
278: ngx_rbt_red(w);
279: ngx_rbtree_right_rotate(root, sentinel, w);
280: w = temp->parent->right;
281: }
282:
283: ngx_rbt_copy_color(w, temp->parent);
284: ngx_rbt_black(temp->parent);
285: ngx_rbt_black(w->right);
286: ngx_rbtree_left_rotate(root, sentinel, temp->parent);
287: temp = *root;
288: }
289:
290: } else {
291: w = temp->parent->left;
292:
293: if (ngx_rbt_is_red(w)) {
294: ngx_rbt_black(w);
295: ngx_rbt_red(temp->parent);
296: ngx_rbtree_right_rotate(root, sentinel, temp->parent);
297: w = temp->parent->left;
298: }
299:
300: if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
301: ngx_rbt_red(w);
302: temp = temp->parent;
303:
304: } else {
305: if (ngx_rbt_is_black(w->left)) {
306: ngx_rbt_black(w->right);
307: ngx_rbt_red(w);
308: ngx_rbtree_left_rotate(root, sentinel, w);
309: w = temp->parent->left;
310: }
311:
312: ngx_rbt_copy_color(w, temp->parent);
313: ngx_rbt_black(temp->parent);
314: ngx_rbt_black(w->left);
315: ngx_rbtree_right_rotate(root, sentinel, temp->parent);
316: temp = *root;
317: }
318: }
319: }
320:
321: ngx_rbt_black(temp);
322: }
323:
324:
325: static ngx_inline void
326: ngx_rbtree_left_rotate(ngx_rbtree_node_t **root, ngx_rbtree_node_t *sentinel,
327: ngx_rbtree_node_t *node)
328: {
329: ngx_rbtree_node_t *temp;
330:
331: temp = node->right;
332: node->right = temp->left;
333:
334: if (temp->left != sentinel) {
335: temp->left->parent = node;
336: }
337:
338: temp->parent = node->parent;
339:
340: if (node == *root) {
341: *root = temp;
342:
343: } else if (node == node->parent->left) {
344: node->parent->left = temp;
345:
346: } else {
347: node->parent->right = temp;
348: }
349:
350: temp->left = node;
351: node->parent = temp;
352: }
353:
354:
355: static ngx_inline void
356: ngx_rbtree_right_rotate(ngx_rbtree_node_t **root, ngx_rbtree_node_t *sentinel,
357: ngx_rbtree_node_t *node)
358: {
359: ngx_rbtree_node_t *temp;
360:
361: temp = node->left;
362: node->left = temp->right;
363:
364: if (temp->right != sentinel) {
365: temp->right->parent = node;
366: }
367:
368: temp->parent = node->parent;
369:
370: if (node == *root) {
371: *root = temp;
372:
373: } else if (node == node->parent->right) {
374: node->parent->right = temp;
375:
376: } else {
377: node->parent->left = temp;
378: }
379:
380: temp->right = node;
381: node->parent = temp;
382: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>