From: Igor Sysoev Date: Sun, 12 Mar 2017 19:40:13 +0000 (+0300) Subject: Using nxt_rbtree_destroy_next() iterator for nxt_mem_cache_pool X-Git-Tag: 0.1.10~26 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=031e6fa9a557b698dc98f9de58f25edd69f12081;p=njs.git Using nxt_rbtree_destroy_next() iterator for nxt_mem_cache_pool destruction without rbtree rebalancing. --- diff --git a/nxt/nxt_mem_cache_pool.c b/nxt/nxt_mem_cache_pool.c index edf3d78e..2a2d2844 100644 --- a/nxt/nxt_mem_cache_pool.c +++ b/nxt/nxt_mem_cache_pool.c @@ -257,19 +257,16 @@ nxt_mem_cache_pool_is_empty(nxt_mem_cache_pool_t *pool) void nxt_mem_cache_pool_destroy(nxt_mem_cache_pool_t *pool) { - void *p; + void *p; nxt_rbtree_node_t *node, *next; nxt_mem_cache_block_t *block; - for (node = nxt_rbtree_min(&pool->blocks); - nxt_rbtree_is_there_successor(&pool->blocks, node); - node = next) - { - next = nxt_rbtree_node_successor(&pool->blocks, node); + next = nxt_rbtree_root(&pool->blocks); - block = (nxt_mem_cache_block_t *) node; + while (next != nxt_rbtree_sentinel(&pool->blocks)) { - nxt_rbtree_delete(&pool->blocks, &block->node); + node = nxt_rbtree_destroy_next(&pool->blocks, &next); + block = (nxt_mem_cache_block_t *) node; p = block->start; diff --git a/nxt/nxt_rbtree.c b/nxt/nxt_rbtree.c index 852317d4..18e8acca 100644 --- a/nxt/nxt_rbtree.c +++ b/nxt/nxt_rbtree.c @@ -495,3 +495,37 @@ nxt_rbtree_parent_relink(nxt_rbtree_node_t *subst, nxt_rbtree_node_t *node) link = (node == parent->left) ? &parent->left : &parent->right; *link = subst; } + + +nxt_rbtree_node_t * +nxt_rbtree_destroy_next(nxt_rbtree_t *tree, nxt_rbtree_node_t **next) +{ + nxt_rbtree_node_t *node, *subst, *parent, *sentinel; + + sentinel = nxt_rbtree_sentinel(tree); + + /* Find the leftmost node. */ + for (node = *next; node->left != sentinel; node = node->left); + + /* Replace the leftmost node with its right child. */ + subst = node->right; + parent = node->parent; + + parent->left = subst; + subst->parent = parent; + + /* + * The right child is used as the next start node. If the right child + * is the sentinel then parent of the leftmost node is used as the next + * start node. The parent of the root node is the sentinel so after + * the single root node will be replaced with the sentinel, the next + * start node will be equal to the sentinel and iteration will stop. + */ + if (subst == sentinel) { + subst = parent; + } + + *next = subst; + + return node; +} diff --git a/nxt/nxt_rbtree.h b/nxt/nxt_rbtree.h index 00adc8bd..9501ad07 100644 --- a/nxt/nxt_rbtree.h +++ b/nxt/nxt_rbtree.h @@ -111,5 +111,16 @@ NXT_EXPORT nxt_rbtree_node_t nxt_rbtree_part_t *node); NXT_EXPORT void nxt_rbtree_delete(nxt_rbtree_t *tree, nxt_rbtree_part_t *node); +/* + * nxt_rbtree_destroy_next() is iterator to use only while rbtree destruction. + * It deletes a node from rbtree and returns the node. The rbtree is not + * rebalanced after deletion. At the beginning the "next" parameter should + * be equal to rbtree root. The iterator should be called in loop until + * the "next" parameter will be equal to the rbtree sentinel. No other + * operations must be performed on the rbtree while destruction. + */ +NXT_EXPORT nxt_rbtree_node_t *nxt_rbtree_destroy_next(nxt_rbtree_t *tree, + nxt_rbtree_node_t **next); + #endif /* _NXT_RBTREE_H_INCLUDED_ */