nfs-ganesha 1.4

splay.c

Go to the documentation of this file.
00001 /*
00002  * splaytree - Implements a top-down threaded splay tree.
00003  *
00004  * Copyright (C) 2010 Franck Bui-Huu <fbuihuu@gmail.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation; version 2 of the
00009  * License.
00010  *
00011  * This library is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00019  * USA
00020  */
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 #include <assert.h>
00025 
00026 #include "avltree.h"
00027 
00028 
00029 #ifdef UINTPTR_MAX
00030 
00031 #define NODE_INIT       { 0, }
00032 
00033 static inline void INIT_NODE(struct splaytree_node *node)
00034 {
00035         node->left = 0;
00036         node->right = 0;
00037 }
00038 
00039 static inline void set_thread(struct splaytree_node *t, uintptr_t *p)
00040 {
00041         *p = (uintptr_t)t | 1;
00042 }
00043 
00044 static inline struct splaytree_node *get_thread(uintptr_t u)
00045 {
00046         return (struct splaytree_node *)((u & -(int)(u & 1)) & ~1UL);
00047 }
00048 
00049 static inline void set_link(struct splaytree_node *n, uintptr_t *p)
00050 {
00051         *p = (uintptr_t)n;
00052 }
00053 
00054 static inline struct splaytree_node *get_link(uintptr_t u)
00055 {
00056         return (struct splaytree_node *)(u & ((int)(u & 1) - 1));
00057 }
00058 
00059 #define set_left(l,n)   set_link(l, &(n)->left)
00060 #define set_right(r,n)  set_link(r, &(n)->right)
00061 #define set_prev(p,n)   set_thread(p, &(n)->left)
00062 #define set_next(s,n)   set_thread(s, &(n)->right)
00063 
00064 #define get_left(n)     get_link((n)->left)
00065 #define get_right(n)    get_link((n)->right)
00066 #define get_prev(n)     get_thread((n)->left)
00067 #define get_next(n)     get_thread((n)->right)
00068 
00069 #else  /* !UINTPTR_MAX */
00070 
00071 #define NODE_INIT       { NULL, }
00072 
00073 static inline void INIT_NODE(struct splaytree_node *node)
00074 {
00075         node->left = NULL;
00076         node->right = NULL;
00077         node->left_is_thread = 0;
00078         node->right_is_thread = 0;
00079 }
00080 
00081 static inline void set_left(struct splaytree_node *l, struct splaytree_node *n)
00082 {
00083         n->left = l;
00084         n->left_is_thread = 0;
00085 }
00086 
00087 static inline void set_right(struct splaytree_node *r, struct splaytree_node *n)
00088 {
00089         n->right = r;
00090         n->right_is_thread = 0;
00091 }
00092 
00093 static inline void set_prev(struct splaytree_node *t, struct splaytree_node *n)
00094 {
00095         n->left = t;
00096         n->left_is_thread = 1;
00097 }
00098 
00099 static inline void set_next(struct splaytree_node *t, struct splaytree_node *n)
00100 {
00101         n->right = t;
00102         n->right_is_thread = 1;
00103 }
00104 
00105 static inline struct splaytree_node *get_left(const struct splaytree_node *n)
00106 {
00107         if (!n->left_is_thread)
00108                 return n->left;
00109         return NULL;
00110 }
00111 
00112 static inline struct splaytree_node *get_right(const struct splaytree_node *n)
00113 {
00114         if (!n->right_is_thread)
00115                 return n->right;
00116         return NULL;
00117 }
00118 
00119 static inline struct splaytree_node *get_prev(const struct splaytree_node *n)
00120 {
00121         if (n->left_is_thread)
00122                 return n->left;
00123         return NULL;
00124 }
00125 
00126 static inline struct splaytree_node *get_next(const struct splaytree_node *n)
00127 {
00128         if (n->right_is_thread)
00129                 return n->right;
00130         return NULL;
00131 }
00132 
00133 #endif  /* UINTPTR_MAX */
00134 
00135 /*
00136  * Iterators
00137  */
00138 static inline struct splaytree_node *get_first(struct splaytree_node *node)
00139 {
00140         struct splaytree_node *left;
00141         while ((left = get_left(node)))
00142                 node = left;
00143         return node;
00144 }
00145 
00146 static inline struct splaytree_node *get_last(struct splaytree_node *node)
00147 {
00148         struct splaytree_node *right;
00149         while ((right = get_right(node)))
00150                 node = right;
00151         return node;
00152 }
00153 
00154 struct splaytree_node *splaytree_first(const struct splaytree *tree)
00155 {
00156         return tree->first;
00157 }
00158 
00159 struct splaytree_node *splaytree_last(const struct splaytree *tree)
00160 {
00161         return tree->last;
00162 }
00163 
00164 struct splaytree_node *splaytree_next(const struct splaytree_node *node)
00165 {
00166         struct splaytree_node *right = get_right(node);
00167         if (right)
00168                 return get_first(right);
00169         return get_next(node);
00170 }
00171 
00172 struct splaytree_node *splaytree_prev(const struct splaytree_node *node)
00173 {
00174         struct splaytree_node *left = get_left(node);
00175         if (left)
00176                 return get_last(left);
00177         return get_prev(node);
00178 }
00179 
00180 static inline void rotate_right(struct splaytree_node *node)
00181 {
00182         struct splaytree_node *left = get_left(node); /* can't be NULL */
00183         struct splaytree_node *r = get_right(left);
00184 
00185         if (r)
00186                 set_left(r, node);
00187         else
00188                 set_prev(left, node);
00189         set_right(node, left);
00190 }
00191 
00192 static inline void rotate_left(struct splaytree_node *node)
00193 {
00194         struct splaytree_node *right = get_right(node); /* can't be NULL */
00195         struct splaytree_node *l = get_left(right);
00196 
00197         if (l)
00198                 set_right(l, node);
00199         else
00200                 set_next(right, node);
00201         set_left(node, right);
00202 }
00203 
00204 static int do_splay(const struct splaytree_node *key,
00205                     struct splaytree *tree)
00206 {
00207         struct splaytree_node subroots = NODE_INIT;
00208         struct splaytree_node *subleft = &subroots, *subright = &subroots;
00209         struct splaytree_node *root = tree->root;
00210         splaytree_cmp_fn_t cmp = tree->cmp_fn;
00211         int rv;
00212 
00213         for (;;) {
00214                 rv = cmp(key, root);
00215                 if (rv == 0)
00216                         break;
00217                 if (rv < 0) {
00218                         struct splaytree_node *left;
00219 
00220                         left = get_left(root);
00221                         if (!left)
00222                                 break;
00223                         if ((rv = cmp(key, left)) < 0) {
00224                                 rotate_right(root);
00225                                 root = left;
00226                                 left = get_left(root);
00227                                 if (!left)
00228                                         break;
00229                         }
00230                         /* link left */
00231                         set_left(root, subright);
00232                         subright = root;
00233                         root = left;
00234                 } else {
00235                         struct splaytree_node *right;
00236 
00237                         right = get_right(root);
00238                         if (!right)
00239                                 break;
00240                         if ((rv = cmp(key, right)) > 0) {
00241                                 rotate_left(root);
00242                                 root = right;
00243                                 right = get_right(root);
00244                                 if (!right)
00245                                         break;
00246                         }
00247                         /* link right */
00248                         set_right(root, subleft);
00249                         subleft = root;
00250                         root = right;
00251                 }
00252         }
00253         /* assemble */
00254         if (get_left(root))
00255                 set_right(get_left(root), subleft);
00256         else
00257                 set_next(root, subleft);
00258 
00259         if (get_right(root))
00260                 set_left(get_right(root), subright);
00261         else
00262                 set_prev(root, subright);
00263 
00264         set_left(get_right(&subroots), root);
00265         set_right(get_left(&subroots), root);
00266         tree->root = root;
00267         return rv;
00268 }
00269 
00270 struct splaytree_node *splaytree_lookup(const struct splaytree_node *key,
00271                                         struct splaytree *tree)
00272 {
00273         if (!tree->root)
00274                 return NULL;
00275         if (do_splay(key, tree) != 0)
00276                 return NULL;
00277         return tree->root;
00278 }
00279 
00280 struct splaytree_node *splaytree_insert(struct splaytree_node *node,
00281                                         struct splaytree *tree)
00282 {
00283         struct splaytree_node *root = tree->root;
00284         int res;
00285 
00286         if (!root) {
00287                 INIT_NODE(node);
00288                 tree->root = node;
00289                 tree->first = node;
00290                 tree->last = node;
00291                 return NULL;
00292         }
00293 
00294         res = do_splay(node, tree);
00295         if (res == 0)
00296                 return tree->root;
00297 
00298         root = tree->root;
00299         if (res < 0) {
00300                 struct splaytree_node *left = get_left(root);
00301 
00302                 set_left(left, node);
00303                 set_right(root, node);
00304                 if (left)
00305                         set_next(node, get_last(left));
00306                 else
00307                         tree->first = node;
00308                 set_prev(node, root);
00309         } else {
00310                 struct splaytree_node *right = get_right(root);
00311 
00312                 set_right(right, node);
00313                 set_left(root, node);
00314                 if (right)
00315                         set_prev(node, get_first(right));
00316                 else
00317                         tree->last = node;
00318                 set_next(node, root);
00319         }
00320         tree->root = node;
00321         return NULL;
00322 }
00323 
00324 void splaytree_remove(struct splaytree_node *node, struct splaytree *tree)
00325 {
00326         struct splaytree_node *right, *left, *prev;
00327 
00328         do_splay(node, tree);
00329         assert(tree->root == node); /* 'node' must be present */
00330 
00331         right = get_right(node);
00332         left  = get_left(node);
00333         if (!left) {
00334                 tree->root = right;
00335                 tree->first = splaytree_next(node);
00336                 prev = NULL;
00337         } else {
00338                 tree->root = left;
00339                 do_splay(node, tree);
00340                 set_right(right, tree->root);
00341                 prev = tree->root;
00342         }
00343         if (right)
00344                 set_prev(prev, get_first(right));
00345         else
00346                 tree->last = prev;
00347 }
00348 
00349 void splaytree_replace(struct splaytree_node *old, struct splaytree_node *new,
00350                        struct splaytree *tree)
00351 {
00352         do_splay(old, tree);
00353         assert(tree->root == old);
00354 
00355         tree->root = new;
00356         if (tree->first == old)
00357                 tree->first = new;
00358         if (tree->last == old)
00359                 tree->last = new;
00360 
00361         *new = *old;
00362 }
00363 
00364 int splaytree_init(struct splaytree *tree, splaytree_cmp_fn_t cmp, unsigned long flags)
00365 {
00366         if (flags)
00367                 return -1;
00368         tree->root = NULL;
00369         tree->first = NULL;
00370         tree->last = NULL;
00371         tree->cmp_fn = cmp;
00372         return 0;
00373 }