Blame rbtree.h

Packit c4abd9
/*
Packit c4abd9
  Red Black Trees
Packit c4abd9
  (C) 1999  Andrea Arcangeli <andrea@suse.de>
Packit c4abd9
  
Packit c4abd9
  This program is free software; you can redistribute it and/or modify
Packit c4abd9
  it under the terms of the GNU General Public License as published by
Packit c4abd9
  the Free Software Foundation; either version 2 of the License, or
Packit c4abd9
  (at your option) any later version.
Packit c4abd9
Packit c4abd9
  This program is distributed in the hope that it will be useful,
Packit c4abd9
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit c4abd9
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit c4abd9
  GNU General Public License for more details.
Packit c4abd9
Packit c4abd9
  You should have received a copy of the GNU General Public License
Packit c4abd9
  along with this program; if not, write to the Free Software
Packit c4abd9
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit c4abd9
Packit c4abd9
  linux/include/linux/rbtree.h
Packit c4abd9
Packit c4abd9
  To use rbtrees you'll have to implement your own insert and search cores.
Packit c4abd9
  This will avoid us to use callbacks and to drop drammatically performances.
Packit c4abd9
  I know it's not the cleaner way,  but in C (not in C++) to get
Packit c4abd9
  performances and genericity...
Packit c4abd9
Packit c4abd9
  Some example of insert and search follows here. The search is a plain
Packit c4abd9
  normal search over an ordered tree. The insert instead must be implemented
Packit c4abd9
  int two steps: as first thing the code must insert the element in
Packit c4abd9
  order as a red leaf in the tree, then the support library function
Packit c4abd9
  rb_insert_color() must be called. Such function will do the
Packit c4abd9
  not trivial work to rebalance the rbtree if necessary.
Packit c4abd9
Packit c4abd9
-----------------------------------------------------------------------
Packit c4abd9
static inline struct page * rb_search_page_cache(struct inode * inode,
Packit c4abd9
						 unsigned long offset)
Packit c4abd9
{
Packit c4abd9
	struct rb_node * n = inode->i_rb_page_cache.rb_node;
Packit c4abd9
	struct page * page;
Packit c4abd9
Packit c4abd9
	while (n)
Packit c4abd9
	{
Packit c4abd9
		page = rb_entry(n, struct page, rb_page_cache);
Packit c4abd9
Packit c4abd9
		if (offset < page->offset)
Packit c4abd9
			n = n->rb_left;
Packit c4abd9
		else if (offset > page->offset)
Packit c4abd9
			n = n->rb_right;
Packit c4abd9
		else
Packit c4abd9
			return page;
Packit c4abd9
	}
Packit c4abd9
	return NULL;
Packit c4abd9
}
Packit c4abd9
Packit c4abd9
static inline struct page * __rb_insert_page_cache(struct inode * inode,
Packit c4abd9
						   unsigned long offset,
Packit c4abd9
						   struct rb_node * node)
Packit c4abd9
{
Packit c4abd9
	struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
Packit c4abd9
	struct rb_node * parent = NULL;
Packit c4abd9
	struct page * page;
Packit c4abd9
Packit c4abd9
	while (*p)
Packit c4abd9
	{
Packit c4abd9
		parent = *p;
Packit c4abd9
		page = rb_entry(parent, struct page, rb_page_cache);
Packit c4abd9
Packit c4abd9
		if (offset < page->offset)
Packit c4abd9
			p = &(*p)->rb_left;
Packit c4abd9
		else if (offset > page->offset)
Packit c4abd9
			p = &(*p)->rb_right;
Packit c4abd9
		else
Packit c4abd9
			return page;
Packit c4abd9
	}
Packit c4abd9
Packit c4abd9
	rb_link_node(node, parent, p);
Packit c4abd9
Packit c4abd9
	return NULL;
Packit c4abd9
}
Packit c4abd9
Packit c4abd9
static inline struct page * rb_insert_page_cache(struct inode * inode,
Packit c4abd9
						 unsigned long offset,
Packit c4abd9
						 struct rb_node * node)
Packit c4abd9
{
Packit c4abd9
	struct page * ret;
Packit c4abd9
	if ((ret = __rb_insert_page_cache(inode, offset, node)))
Packit c4abd9
		goto out;
Packit c4abd9
	rb_insert_color(node, &inode->i_rb_page_cache);
Packit c4abd9
 out:
Packit c4abd9
	return ret;
Packit c4abd9
}
Packit c4abd9
-----------------------------------------------------------------------
Packit c4abd9
*/
Packit c4abd9
Packit c4abd9
#ifndef	_LINUX_RBTREE_H
Packit c4abd9
#define	_LINUX_RBTREE_H
Packit c4abd9
Packit c4abd9
#include <stdlib.h>
Packit c4abd9
Packit c4abd9
struct rb_node
Packit c4abd9
{
Packit c4abd9
	unsigned long  rb_parent_color;
Packit c4abd9
#define	RB_RED		0
Packit c4abd9
#define	RB_BLACK	1
Packit c4abd9
	struct rb_node *rb_right;
Packit c4abd9
	struct rb_node *rb_left;
Packit c4abd9
};
Packit c4abd9
Packit c4abd9
struct rb_root
Packit c4abd9
{
Packit c4abd9
	struct rb_node *rb_node;
Packit c4abd9
};
Packit c4abd9
Packit c4abd9
#undef offsetof
Packit c4abd9
#ifdef __compiler_offsetof
Packit c4abd9
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
Packit c4abd9
#else
Packit c4abd9
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Packit c4abd9
#endif
Packit c4abd9
Packit c4abd9
#define container_of(ptr, type, member) ({                      \
Packit c4abd9
	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
Packit c4abd9
	(type *)( (char *)__mptr - offsetof(type,member) );})
Packit c4abd9
Packit c4abd9
#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
Packit c4abd9
#define rb_color(r)   ((r)->rb_parent_color & 1)
Packit c4abd9
#define rb_is_red(r)   (!rb_color(r))
Packit c4abd9
#define rb_is_black(r) rb_color(r)
Packit c4abd9
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
Packit c4abd9
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
Packit c4abd9
Packit c4abd9
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
Packit c4abd9
{
Packit c4abd9
	rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
Packit c4abd9
}
Packit c4abd9
static inline void rb_set_color(struct rb_node *rb, int color)
Packit c4abd9
{
Packit c4abd9
	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
Packit c4abd9
}
Packit c4abd9
Packit c4abd9
#define RB_ROOT	(struct rb_root) { NULL, }
Packit c4abd9
#define	rb_entry(ptr, type, member) container_of(ptr, type, member)
Packit c4abd9
Packit c4abd9
extern void rb_insert_color(struct rb_node *, struct rb_root *);
Packit c4abd9
extern void rb_erase(struct rb_node *, struct rb_root *);
Packit c4abd9
Packit c4abd9
/* Find logical next and previous nodes in a tree */
Packit c4abd9
extern struct rb_node *rb_next(struct rb_node *);
Packit c4abd9
extern struct rb_node *rb_prev(struct rb_node *);
Packit c4abd9
extern struct rb_node *rb_first(struct rb_root *);
Packit c4abd9
extern struct rb_node *rb_last(struct rb_root *);
Packit c4abd9
Packit c4abd9
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
Packit c4abd9
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
Packit c4abd9
			    struct rb_root *root);
Packit c4abd9
Packit c4abd9
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
Packit c4abd9
				struct rb_node ** rb_link)
Packit c4abd9
{
Packit c4abd9
	node->rb_parent_color = (unsigned long )parent;
Packit c4abd9
	node->rb_left = node->rb_right = NULL;
Packit c4abd9
Packit c4abd9
	*rb_link = node;
Packit c4abd9
}
Packit c4abd9
Packit c4abd9
#endif	/* _LINUX_RBTREE_H */