Annotation of embedaddon/nginx/src/core/ngx_rbtree.c, revision 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>