haproxy/include/import/eb32sctree.h
Willy Tarreau 8d2b777fe3 REORG: ebtree: move the include files from ebtree to include/import/
This is where other imported components are located. All files which
used to directly include ebtree were touched to update their include
path so that "import/" is now prefixed before the ebtree-related files.

The ebtree.h file was slightly adjusted to read compiler.h from the
common/ subdirectory (this is the only change).

A build issue was encountered when eb32sctree.h is loaded before
eb32tree.h because only the former checks for the latter before
defining type u32. This was addressed by adding the reverse ifdef
in eb32tree.h.

No further cleanup was done yet in order to keep changes minimal.
2020-06-11 09:31:11 +02:00

146 lines
5.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)
/* These types may sometimes already be defined */
#ifndef _EB32TREE_H
typedef unsigned int u32;
typedef signed int s32;
#endif
/* This structure carries a node, a leaf, a scope, and a key. It must start
* with the eb_node so that it can be cast into an eb_node. We could also
* have put some sort of transparent union here to reduce the indirection
* level, but the fact is, the end user is not meant to manipulate internals,
* so this is pointless.
* In case sizeof(void*)>=sizeof(long), we know there will be some padding after
* the leaf if it's unaligned. In this case we force the alignment on void* so
* that we prefer to have the padding before for more efficient accesses.
*/
struct eb32sc_node {
struct eb_node node; /* the tree node, must be at the beginning */
MAYBE_ALIGN(sizeof(u32));
u32 key;
ALWAYS_ALIGN(sizeof(void*));
unsigned long node_s; /* visibility of this node's branches */
unsigned long leaf_s; /* visibility of this node's leaf */
} ALIGNED(sizeof(void*));
/*
* 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 */