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>