mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-12 06:24:56 +00:00
9b7a617a0e
ebtree is one piece using a lot of inlines and each tree root or node definition needed by many of our structures requires to parse and compile all these includes, which is large and painfully slow. Let's move the very basic definitions to their own file and include it from ebtree.h.
122 lines
4.1 KiB
C
122 lines
4.1 KiB
C
/*
|
|
* Elastic Binary Trees - macros and structures for operations on 32bit nodes.
|
|
* Version 6.0.6 with backports from v7-dev
|
|
* (C) 2002-2017 - Willy Tarreau <w@1wt.eu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
* exclusively.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _EB32SCTREE_H
|
|
#define _EB32SCTREE_H
|
|
|
|
#include "ebtree.h"
|
|
|
|
|
|
/* Return the structure of type <type> whose member <member> points to <ptr> */
|
|
#define eb32sc_entry(ptr, type, member) container_of(ptr, type, member)
|
|
|
|
/*
|
|
* Exported functions and macros.
|
|
* Many of them are always inlined because they are extremely small, and
|
|
* are generally called at most once or twice in a program.
|
|
*/
|
|
|
|
/*
|
|
* The following functions are not inlined by default. They are declared
|
|
* in eb32sctree.c, which simply relies on their inline version.
|
|
*/
|
|
struct eb32sc_node *eb32sc_lookup_ge(struct eb_root *root, u32 x, unsigned long scope);
|
|
struct eb32sc_node *eb32sc_lookup_ge_or_first(struct eb_root *root, u32 x, unsigned long scope);
|
|
struct eb32sc_node *eb32sc_insert(struct eb_root *root, struct eb32sc_node *new, unsigned long scope);
|
|
void eb32sc_delete(struct eb32sc_node *node);
|
|
|
|
/* Walks down left starting at root pointer <start>, and follow the leftmost
|
|
* branch whose scope matches <scope>. It either returns the node hosting the
|
|
* first leaf on that side, or NULL if no leaf is found. <start> may either be
|
|
* NULL or a branch pointer. The pointer to the leaf (or NULL) is returned.
|
|
*/
|
|
static inline struct eb32sc_node *eb32sc_walk_down_left(eb_troot_t *start, unsigned long scope)
|
|
{
|
|
struct eb_root *root;
|
|
struct eb_node *node;
|
|
struct eb32sc_node *eb32;
|
|
|
|
if (unlikely(!start))
|
|
return NULL;
|
|
|
|
while (1) {
|
|
if (eb_gettag(start) == EB_NODE) {
|
|
root = eb_untag(start, EB_NODE);
|
|
node = eb_root_to_node(root);
|
|
eb32 = container_of(node, struct eb32sc_node, node);
|
|
if (eb32->node_s & scope) {
|
|
start = node->branches.b[EB_LEFT];
|
|
continue;
|
|
}
|
|
start = node->node_p;
|
|
}
|
|
else {
|
|
root = eb_untag(start, EB_LEAF);
|
|
node = eb_root_to_node(root);
|
|
eb32 = container_of(node, struct eb32sc_node, node);
|
|
if (eb32->leaf_s & scope)
|
|
return eb32;
|
|
start = node->leaf_p;
|
|
}
|
|
|
|
/* here we're on a node that doesn't match the scope. We have
|
|
* to walk to the closest right location.
|
|
*/
|
|
while (eb_gettag(start) != EB_LEFT)
|
|
/* Walking up from right branch, so we cannot be below root */
|
|
start = (eb_root_to_node(eb_untag(start, EB_RGHT)))->node_p;
|
|
|
|
/* Note that <start> cannot be NULL at this stage */
|
|
root = eb_untag(start, EB_LEFT);
|
|
start = root->b[EB_RGHT];
|
|
if (eb_clrtag(start) == NULL)
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Return next node in the tree, starting with tagged parent <start>, or NULL if none */
|
|
static inline struct eb32sc_node *eb32sc_next_with_parent(eb_troot_t *start, unsigned long scope)
|
|
{
|
|
while (eb_gettag(start) != EB_LEFT)
|
|
/* Walking up from right branch, so we cannot be below root */
|
|
start = (eb_root_to_node(eb_untag(start, EB_RGHT)))->node_p;
|
|
|
|
/* Note that <t> cannot be NULL at this stage */
|
|
start = (eb_untag(start, EB_LEFT))->b[EB_RGHT];
|
|
if (eb_clrtag(start) == NULL)
|
|
return NULL;
|
|
|
|
return eb32sc_walk_down_left(start, scope);
|
|
}
|
|
|
|
/* Return next node in the tree, or NULL if none */
|
|
static inline struct eb32sc_node *eb32sc_next(struct eb32sc_node *eb32, unsigned long scope)
|
|
{
|
|
return eb32sc_next_with_parent(eb32->node.leaf_p, scope);
|
|
}
|
|
|
|
/* Return leftmost node in the tree, or NULL if none */
|
|
static inline struct eb32sc_node *eb32sc_first(struct eb_root *root, unsigned long scope)
|
|
{
|
|
return eb32sc_walk_down_left(root->b[0], scope);
|
|
}
|
|
|
|
#endif /* _EB32SC_TREE_H */
|