From 8c5f37e7d3081598090669a74c34facee96134b1 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Thu, 16 Nov 2006 15:34:52 +0000 Subject: [PATCH] rbtree insert procedure --- src/core/ngx_rbtree.c | 91 ++++++++++++++++++------------------- src/core/ngx_rbtree.h | 9 ++-- src/event/ngx_event_timer.c | 1 + 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c index 88673a264..ae973e5b0 100644 --- a/src/core/ngx_rbtree.c +++ b/src/core/ngx_rbtree.c @@ -47,53 +47,10 @@ ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree, return; } - /* - * The rbtree is currently used by event timers only. Timer values - * 1) are spread in small range, usually several minutes, - * 2) and overflow each 49 days, if milliseconds are stored in 32 bits. - * The below comparison takes into account that overflow. - * - * If there will be a necessity to use the rbtree for values with - * other comparison rules, then a whole "for ( ;; )" loop should - * be made as tree->insert() function. - */ - - temp = *root; - - for ( ;; ) { - - /* node->key < temp->key */ - - if ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key - < 0) - { - if (temp->left == sentinel) { - temp->left = node; - break; - } - - temp = temp->left; - continue; - } - - if (temp->right == sentinel) { - temp->right = node; - break; - } - - temp = temp->right; - continue; - } - - node->parent = temp; - node->left = sentinel; - node->right = sentinel; - + tree->insert(*root, node, sentinel); /* re-balance tree */ - ngx_rbt_red(node); - while (node != *root && ngx_rbt_is_red(node->parent)) { if (node->parent == node->parent->parent->left) { @@ -136,18 +93,60 @@ ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree, ngx_rbtree_left_rotate(root, sentinel, node->parent->parent); } } - } ngx_rbt_black(*root); } +void +ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, + ngx_rbtree_node_t *sentinel) +{ + for ( ;; ) { + + /* + * Timer values + * 1) are spread in small range, usually several minutes, + * 2) and overflow each 49 days, if milliseconds are stored in 32 bits. + * The comparison takes into account that overflow. + */ + + if ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key + < 0) + { + /* node->key < temp->key */ + + if (temp->left == sentinel) { + temp->left = node; + break; + } + + temp = temp->left; + + } else { + + if (temp->right == sentinel) { + temp->right = node; + break; + } + + temp = temp->right; + } + } + + node->parent = temp; + node->left = sentinel; + node->right = sentinel; + ngx_rbt_red(node); +} + + void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree, ngx_rbtree_node_t *node) { - ngx_int_t red; + ngx_uint_t red; ngx_rbtree_node_t **root, *sentinel, *subst, *temp, *w; /* a binary tree delete */ diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h index a57ec778d..c03703dc2 100644 --- a/src/core/ngx_rbtree.h +++ b/src/core/ngx_rbtree.h @@ -23,19 +23,20 @@ struct ngx_rbtree_node_s { ngx_rbtree_node_t *left; ngx_rbtree_node_t *right; ngx_rbtree_node_t *parent; - char color; + u_char color; + u_char data; }; typedef struct ngx_rbtree_s ngx_rbtree_t; -typedef ngx_rbtree_node_t *(*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root, +typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); struct ngx_rbtree_s { ngx_rbtree_node_t *root; ngx_rbtree_node_t *sentinel; - /* ngx_rbtree_insert_pt insert; */ + ngx_rbtree_insert_pt insert; }; @@ -43,6 +44,8 @@ void ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree, ngx_rbtree_node_t *node); void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree, ngx_rbtree_node_t *node); +void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root, + ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); static ngx_inline ngx_rbtree_node_t * diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c index 3eb23f6d3..ababb819a 100644 --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -23,6 +23,7 @@ ngx_event_timer_init(ngx_log_t *log) { ngx_event_timer_rbtree.root = &ngx_event_timer_sentinel; ngx_event_timer_rbtree.sentinel = &ngx_event_timer_sentinel; + ngx_event_timer_rbtree.insert = ngx_rbtree_insert_timer_value; #if (NGX_THREADS)