Move out of misc/ and put in own folder and add the grouping to doxygen to be able to reference the doxygen docs into RST. Move each item into their own file to reduce clutter and to make it less crowded in one single page. Signed-off-by: Anas Nashif <anas.nashif@intel.com>
223 lines
6.8 KiB
C
223 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/* Our SDK/toolchains integration seems to be inconsistent about
|
|
* whether they expose alloca.h or not. On gcc it's a moot point as
|
|
* it's always builtin.
|
|
*/
|
|
#ifdef __GNUC__
|
|
#ifndef alloca
|
|
#define alloca __builtin_alloca
|
|
#endif
|
|
#else
|
|
#include <alloca.h>
|
|
#endif
|
|
|
|
/**
|
|
* @file
|
|
* @brief Red/Black balanced tree data structure
|
|
*
|
|
* This implements an intrusive balanced tree that guarantees
|
|
* O(log2(N)) runtime for all operations and amortized O(1) behavior
|
|
* for creation and destruction of whole trees. The algorithms and
|
|
* naming are conventional per existing academic and didactic
|
|
* implementations, c.f.:
|
|
*
|
|
* https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
|
|
*
|
|
* The implementation is size-optimized to prioritize runtime memory
|
|
* usage. The data structure is intrusive, which is to say the struct
|
|
* rbnode handle is intended to be placed in a separate struct the
|
|
* same way other such structures (e.g. Zephyr's dlist list) and
|
|
* requires no data pointer to be stored in the node. The color bit
|
|
* is unioned with a pointer (fairly common for such libraries). Most
|
|
* notably, there is no "parent" pointer stored in the node, the upper
|
|
* structure of the tree being generated dynamically via a stack as
|
|
* the tree is recursed. So the overall memory overhead of a node is
|
|
* just two pointers, identical with a doubly-linked list.
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_SYS_RB_H_
|
|
#define ZEPHYR_INCLUDE_SYS_RB_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
struct rbnode {
|
|
struct rbnode *children[2];
|
|
};
|
|
|
|
/* Theoretical maximum depth of tree based on pointer size. If memory
|
|
* is filled with 2-pointer nodes, and the tree can be twice as a
|
|
* packed binary tree, plus root... Works out to 59 entries for 32
|
|
* bit pointers and 121 at 64 bits.
|
|
*/
|
|
#define Z_TBITS(t) ((sizeof(t)) < 8 ? 2 : 3)
|
|
#define Z_PBITS(t) (8 * sizeof(t))
|
|
#define Z_MAX_RBTREE_DEPTH (2 * (Z_PBITS(int *) - Z_TBITS(int *) - 1) + 1)
|
|
|
|
|
|
/**
|
|
* @defgroup rbtree_apis Balanced Red/Black Tree
|
|
* @ingroup datastructure_apis
|
|
* @{
|
|
*/
|
|
/**
|
|
* @typedef rb_lessthan_t
|
|
* @brief Red/black tree comparison predicate
|
|
*
|
|
* Compares the two nodes and returns true if node A is strictly less
|
|
* than B according to the tree's sorting criteria, false otherwise.
|
|
*
|
|
* Note that during insert, the new node being inserted will always be
|
|
* "A", where "B" is the existing node within the tree against which
|
|
* it is being compared. This trait can be used (with care!) to
|
|
* implement "most/least recently added" semantics between nodes which
|
|
* would otherwise compare as equal.
|
|
*/
|
|
typedef bool (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b);
|
|
|
|
struct rbtree {
|
|
struct rbnode *root;
|
|
rb_lessthan_t lessthan_fn;
|
|
int max_depth;
|
|
#ifdef CONFIG_MISRA_SANE
|
|
struct rbnode *iter_stack[Z_MAX_RBTREE_DEPTH];
|
|
unsigned char iter_left[Z_MAX_RBTREE_DEPTH];
|
|
#endif
|
|
};
|
|
|
|
typedef void (*rb_visit_t)(struct rbnode *node, void *cookie);
|
|
|
|
struct rbnode *z_rb_child(struct rbnode *node, int side);
|
|
int z_rb_is_black(struct rbnode *node);
|
|
#ifndef CONFIG_MISRA_SANE
|
|
void z_rb_walk(struct rbnode *node, rb_visit_t visit_fn, void *cookie);
|
|
#endif
|
|
struct rbnode *z_rb_get_minmax(struct rbtree *tree, int side);
|
|
|
|
/**
|
|
* @brief Insert node into tree
|
|
*/
|
|
void rb_insert(struct rbtree *tree, struct rbnode *node);
|
|
|
|
/**
|
|
* @brief Remove node from tree
|
|
*/
|
|
void rb_remove(struct rbtree *tree, struct rbnode *node);
|
|
|
|
/**
|
|
* @brief Returns the lowest-sorted member of the tree
|
|
*/
|
|
static inline struct rbnode *rb_get_min(struct rbtree *tree)
|
|
{
|
|
return z_rb_get_minmax(tree, 0);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the highest-sorted member of the tree
|
|
*/
|
|
static inline struct rbnode *rb_get_max(struct rbtree *tree)
|
|
{
|
|
return z_rb_get_minmax(tree, 1);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true if the given node is part of the tree
|
|
*
|
|
* Note that this does not internally dereference the node pointer
|
|
* (though the tree's lessthan callback might!), it just tests it for
|
|
* equality with items in the tree. So it's feasible to use this to
|
|
* implement a "set" construct by simply testing the pointer value
|
|
* itself.
|
|
*/
|
|
bool rb_contains(struct rbtree *tree, struct rbnode *node);
|
|
|
|
#ifndef CONFIG_MISRA_SANE
|
|
/**
|
|
* @brief Walk/enumerate a rbtree
|
|
*
|
|
* Very simple recursive enumeration. Low code size, but requiring a
|
|
* separate function can be clumsy for the user and there is no way to
|
|
* break out of the loop early. See RB_FOR_EACH for an iterative
|
|
* implementation.
|
|
*/
|
|
static inline void rb_walk(struct rbtree *tree, rb_visit_t visit_fn,
|
|
void *cookie)
|
|
{
|
|
z_rb_walk(tree->root, visit_fn, cookie);
|
|
}
|
|
#endif
|
|
|
|
struct _rb_foreach {
|
|
struct rbnode **stack;
|
|
char *is_left;
|
|
int top;
|
|
};
|
|
|
|
#ifdef CONFIG_MISRA_SANE
|
|
#define _RB_FOREACH_INIT(tree, node) { \
|
|
.stack = &(tree)->iter_stack[0], \
|
|
.is_left = &(tree)->iter_left[0], \
|
|
.top = -1 \
|
|
}
|
|
#else
|
|
#define _RB_FOREACH_INIT(tree, node) { \
|
|
.stack = (struct rbnode **) \
|
|
alloca((tree)->max_depth * sizeof(struct rbnode *)), \
|
|
.is_left = (char *)alloca((tree)->max_depth * sizeof(char)), \
|
|
.top = -1 \
|
|
}
|
|
#endif
|
|
|
|
struct rbnode *z_rb_foreach_next(struct rbtree *tree, struct _rb_foreach *f);
|
|
|
|
/**
|
|
* @brief Walk a tree in-order without recursing
|
|
*
|
|
* While @ref rb_walk() is very simple, recursing on the C stack can
|
|
* be clumsy for some purposes and on some architectures wastes
|
|
* significant memory in stack frames. This macro implements a
|
|
* non-recursive "foreach" loop that can iterate directly on the tree,
|
|
* at a moderate cost in code size.
|
|
*
|
|
* Note that the resulting loop is not safe against modifications to
|
|
* the tree. Changes to the tree structure during the loop will
|
|
* produce incorrect results, as nodes may be skipped or duplicated.
|
|
* Unlike linked lists, no _SAFE variant exists.
|
|
*
|
|
* Note also that the macro expands its arguments multiple times, so
|
|
* they should not be expressions with side effects.
|
|
*
|
|
* @param tree A pointer to a struct rbtree to walk
|
|
* @param node The symbol name of a local struct rbnode* variable to
|
|
* use as the iterator
|
|
*/
|
|
#define RB_FOR_EACH(tree, node) \
|
|
for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node); \
|
|
(node = z_rb_foreach_next(tree, &__f)); \
|
|
/**/)
|
|
|
|
/**
|
|
* @brief Loop over rbtree with implicit container field logic
|
|
*
|
|
* As for RB_FOR_EACH(), but "node" can have an arbitrary type
|
|
* containing a struct rbnode.
|
|
*
|
|
* @param tree A pointer to a struct rbtree to walk
|
|
* @param node The symbol name of a local iterator
|
|
* @param field The field name of a struct rbnode inside node
|
|
*/
|
|
#define RB_FOR_EACH_CONTAINER(tree, node, field) \
|
|
for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node); \
|
|
({struct rbnode *n = z_rb_foreach_next(tree, &__f); \
|
|
node = n ? CONTAINER_OF(n, __typeof__(*(node)), \
|
|
field) : NULL; }) != NULL; \
|
|
/**/)
|
|
|
|
/** @} */
|
|
|
|
#endif /* ZEPHYR_INCLUDE_SYS_RB_H_ */
|