| 1 |
/* Stolen from Linux 2.6.34 */ |
| 2 |
|
| 3 |
/* |
| 4 |
Red Black Trees |
| 5 |
(C) 1999 Andrea Arcangeli <andrea@suse.de> |
| 6 |
|
| 7 |
This program is free software; you can redistribute it and/or modify |
| 8 |
it under the terms of the GNU General Public License as published by |
| 9 |
the Free Software Foundation; either version 2 of the License, or |
| 10 |
(at your option) any later version. |
| 11 |
|
| 12 |
This program is distributed in the hope that it will be useful, |
| 13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 |
GNU General Public License for more details. |
| 16 |
|
| 17 |
You should have received a copy of the GNU General Public License |
| 18 |
along with this program; if not, see <http://www.gnu.org/licenses/>. |
| 19 |
|
| 20 |
linux/include/linux/rbtree.h |
| 21 |
|
| 22 |
To use rbtrees you'll have to implement your own insert and search cores. |
| 23 |
This will avoid us to use callbacks and to drop drammatically performances. |
| 24 |
I know it's not the cleaner way, but in C (not in C++) to get |
| 25 |
performances and genericity... |
| 26 |
|
| 27 |
Some example of insert and search follows here. The search is a plain |
| 28 |
normal search over an ordered tree. The insert instead must be implemented |
| 29 |
int two steps: as first thing the code must insert the element in |
| 30 |
order as a red leaf in the tree, then the support library function |
| 31 |
rb_insert_color() must be called. Such function will do the |
| 32 |
not trivial work to rebalance the rbtree if necessary. |
| 33 |
|
| 34 |
----------------------------------------------------------------------- |
| 35 |
static inline struct page * rb_search_page_cache(struct inode * inode, |
| 36 |
unsigned long offset) |
| 37 |
{ |
| 38 |
struct rb_node * n = inode->i_rb_page_cache.rb_node; |
| 39 |
struct page * page; |
| 40 |
|
| 41 |
while (n) |
| 42 |
{ |
| 43 |
page = rb_entry(n, struct page, rb_page_cache); |
| 44 |
|
| 45 |
if (offset < page->offset) |
| 46 |
n = n->rb_left; |
| 47 |
else if (offset > page->offset) |
| 48 |
n = n->rb_right; |
| 49 |
else |
| 50 |
return page; |
| 51 |
} |
| 52 |
return NULL; |
| 53 |
} |
| 54 |
|
| 55 |
static inline struct page * __rb_insert_page_cache(struct inode * inode, |
| 56 |
unsigned long offset, |
| 57 |
struct rb_node * node) |
| 58 |
{ |
| 59 |
struct rb_node ** p = &inode->i_rb_page_cache.rb_node; |
| 60 |
struct rb_node * parent = NULL; |
| 61 |
struct page * page; |
| 62 |
|
| 63 |
while (*p) |
| 64 |
{ |
| 65 |
parent = *p; |
| 66 |
page = rb_entry(parent, struct page, rb_page_cache); |
| 67 |
|
| 68 |
if (offset < page->offset) |
| 69 |
p = &(*p)->rb_left; |
| 70 |
else if (offset > page->offset) |
| 71 |
p = &(*p)->rb_right; |
| 72 |
else |
| 73 |
return page; |
| 74 |
} |
| 75 |
|
| 76 |
rb_link_node(node, parent, p); |
| 77 |
|
| 78 |
return NULL; |
| 79 |
} |
| 80 |
|
| 81 |
static inline struct page * rb_insert_page_cache(struct inode * inode, |
| 82 |
unsigned long offset, |
| 83 |
struct rb_node * node) |
| 84 |
{ |
| 85 |
struct page * ret; |
| 86 |
if ((ret = __rb_insert_page_cache(inode, offset, node))) |
| 87 |
goto out; |
| 88 |
rb_insert_color(node, &inode->i_rb_page_cache); |
| 89 |
out: |
| 90 |
return ret; |
| 91 |
} |
| 92 |
----------------------------------------------------------------------- |
| 93 |
*/ |
| 94 |
|
| 95 |
#ifndef _LINUX_RBTREE_H |
| 96 |
#define _LINUX_RBTREE_H |
| 97 |
|
| 98 |
#include "compiler.h" /* container_of */ |
| 99 |
#include <stddef.h> |
| 100 |
|
| 101 |
struct rb_node |
| 102 |
{ |
| 103 |
unsigned long rb_parent_color; |
| 104 |
#define RB_RED 0 |
| 105 |
#define RB_BLACK 1 |
| 106 |
struct rb_node *rb_right; |
| 107 |
struct rb_node *rb_left; |
| 108 |
} __attribute__((aligned(sizeof(long)))); |
| 109 |
/* The alignment might seem pointless, but allegedly CRIS needs it */ |
| 110 |
|
| 111 |
struct rb_root |
| 112 |
{ |
| 113 |
struct rb_node *rb_node; |
| 114 |
}; |
| 115 |
|
| 116 |
|
| 117 |
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) |
| 118 |
#define rb_color(r) ((r)->rb_parent_color & 1) |
| 119 |
#define rb_is_red(r) (!rb_color(r)) |
| 120 |
#define rb_is_black(r) rb_color(r) |
| 121 |
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) |
| 122 |
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) |
| 123 |
|
| 124 |
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) |
| 125 |
{ |
| 126 |
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; |
| 127 |
} |
| 128 |
static inline void rb_set_color(struct rb_node *rb, int color) |
| 129 |
{ |
| 130 |
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; |
| 131 |
} |
| 132 |
|
| 133 |
#define RB_ROOT (struct rb_root) { NULL, } |
| 134 |
#define rb_entry(ptr, type, member) container_of(ptr, type, member) |
| 135 |
|
| 136 |
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) |
| 137 |
#define RB_EMPTY_NODE(node) (rb_parent(node) == node) |
| 138 |
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) |
| 139 |
|
| 140 |
void rb_insert_color(struct rb_node *, struct rb_root *); |
| 141 |
void rb_erase(struct rb_node *, struct rb_root *); |
| 142 |
|
| 143 |
/* Find logical next and previous nodes in a tree */ |
| 144 |
struct rb_node *rb_next(const struct rb_node *); |
| 145 |
struct rb_node *rb_prev(const struct rb_node *); |
| 146 |
struct rb_node *rb_first(const struct rb_root *); |
| 147 |
struct rb_node *rb_last(const struct rb_root *); |
| 148 |
|
| 149 |
/* Fast replacement of a single node without remove/rebalance/add/rebalance */ |
| 150 |
void rb_replace_node(struct rb_node *victim, struct rb_node *new, |
| 151 |
struct rb_root *root); |
| 152 |
|
| 153 |
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, |
| 154 |
struct rb_node ** rb_link) |
| 155 |
{ |
| 156 |
node->rb_parent_color = (unsigned long )parent; |
| 157 |
node->rb_left = node->rb_right = NULL; |
| 158 |
|
| 159 |
*rb_link = node; |
| 160 |
} |
| 161 |
|
| 162 |
|
| 163 |
/* Cmus extensions */ |
| 164 |
|
| 165 |
static inline void rb_root_init(struct rb_root *root) |
| 166 |
{ |
| 167 |
root->rb_node = NULL; |
| 168 |
} |
| 169 |
|
| 170 |
static inline int rb_root_empty(struct rb_root *root) |
| 171 |
{ |
| 172 |
return RB_EMPTY_ROOT(root); |
| 173 |
} |
| 174 |
|
| 175 |
/** |
| 176 |
* rb_for_each - iterate over a rbtree |
| 177 |
* @pos: the &struct rb_node to use as a loop counter. |
| 178 |
* @root: the root for your rbtree. |
| 179 |
*/ |
| 180 |
#define rb_for_each(pos, root) \ |
| 181 |
for (pos = rb_first(root); pos; pos = rb_next(pos)) |
| 182 |
|
| 183 |
/** |
| 184 |
* rb_for_each_prev - iterate over a rbtree backwards |
| 185 |
* @pos: the &struct rb_node to use as a loop counter. |
| 186 |
* @root: the root for your rbtree. |
| 187 |
*/ |
| 188 |
#define rb_for_each_prev(pos, root) \ |
| 189 |
for (pos = rb_last(root); pos; pos = rb_prev(pos)) |
| 190 |
|
| 191 |
/** |
| 192 |
* rb_for_each_safe - iterate over a rbtree safe against removal of rbtree node |
| 193 |
* @pos: the &struct rb_node to use as a loop counter. |
| 194 |
* @n: another &struct rb_node to use as temporary storage |
| 195 |
* @root: the root for your rbtree. |
| 196 |
*/ |
| 197 |
#define rb_for_each_safe(pos, n, root) \ |
| 198 |
for (pos = rb_first(root), n = pos ? rb_next(pos) : NULL; pos; \ |
| 199 |
pos = n, n = pos ? rb_next(pos) : NULL) |
| 200 |
|
| 201 |
/** |
| 202 |
* rb_for_each_entry - iterate over a rbtree of given type |
| 203 |
* @pos: the &struct rb_node to use as a loop counter. |
| 204 |
* @t: the type * to use as a loop counter. |
| 205 |
* @root: the root for your rbtree. |
| 206 |
* @member: the name of the rb_node-struct within the struct. |
| 207 |
*/ |
| 208 |
#define rb_for_each_entry(t, pos, root, member) \ |
| 209 |
for (pos = rb_first(root), t = pos ? rb_entry(pos, __typeof__(*t), member) : NULL; \ |
| 210 |
pos; pos = rb_next(pos), t = pos ? rb_entry(pos, __typeof__(*t), member) : NULL) |
| 211 |
|
| 212 |
/** |
| 213 |
* rb_for_each_entry_reverse - iterate backwards over a rbtree of given type |
| 214 |
* @pos: the &struct rb_node to use as a loop counter. |
| 215 |
* @t: the type * to use as a loop counter. |
| 216 |
* @root: the root for your rbtree. |
| 217 |
* @member: the name of the rb_node-struct within the struct. |
| 218 |
*/ |
| 219 |
#define rb_for_each_entry_reverse(t, pos, root, member) \ |
| 220 |
for (pos = rb_last(root), t = pos ? rb_entry(pos, __typeof__(*t), member) : NULL; \ |
| 221 |
pos; pos = rb_prev(pos), t = pos ? rb_entry(pos, __typeof__(*t), member) : NULL) |
| 222 |
|
| 223 |
#endif /* _LINUX_RBTREE_H */ |