80 #if defined(AO2_DEBUG) 83 int fixup_insert_left[3];
85 int fixup_insert_right[3];
87 int fixup_delete_left[4];
89 int fixup_delete_right[4];
91 int delete_children[3];
157 while (node->
right) {
278 while (node->
right) {
368 cmp = sort_fn(right_most->
common.
obj, obj_right, flags);
385 cmp = sort_fn(cur->
common.
obj, obj_right, flags);
408 if (cur->
parent == empty) {
422 cmp = sort_fn(cur->
common.
obj, obj_right, flags);
559 const char *tag,
const char *
file,
int line,
const char *func)
566 self->common.sort_fn, self->common.cmp_fn, tag, file, line, func);
588 while (self->root != child && !child->
is_red) {
637 if (sibling->
right) {
756 if (next->
right == next) {
758 next->
right = doomed;
772 child = doomed->
right;
775 child = doomed->
left;
777 child = doomed->
right;
786 need_fixup = (!doomed->
is_red && !
self->common.destroying);
787 if (need_fixup && !child) {
865 #if defined(AO2_DEBUG) 872 #if defined(AO2_DEBUG) 914 __ao2_ref(obj_new, +1, tag ?:
"Container node creation", file, line, func);
1009 self->root->is_red = 0;
1037 sort_fn =
self->common.sort_fn;
1038 options =
self->common.options;
1102 }
else if (cmp < 0) {
1147 switch (options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
1278 flags = state->
flags;
1362 sort_fn =
self->common.sort_fn;
1392 cmp = sort_fn(next->
common.
obj, obj_right, sort_flags);
1404 cmp = sort_fn(node->
common.
obj, obj_right, sort_flags);
1407 }
else if (cmp < 0) {
1443 cmp = sort_fn(next->
common.
obj, obj_right, sort_flags);
1476 if (self->common.destroying) {
1481 memset(state, 0,
sizeof(*state));
1483 state->
flags = flags;
1490 state->
sort_fn =
self->common.sort_fn;
1684 ast_log(
LOG_ERROR,
"Node ref leak. Red-Black tree container still has nodes!\n");
1689 #if defined(AO2_DEBUG) 1704 #define FORMAT "%16s, %16s, %16s, %16s, %5s, %16s, %s\n" 1705 #define FORMAT2 "%16p, %16p, %16p, %16p, %5s, %16p, " 1709 prnt(where,
FORMAT,
"Node",
"Parent",
"Left",
"Right",
"Color",
"Obj",
"Key");
1710 for (node = self->root; node; node =
rb_node_pre(node)) {
1716 node->
is_red ?
"Red" :
"Black",
1719 prnt_obj(node->
common.
obj, where, prnt);
1729 #if defined(AO2_DEBUG) 1747 for (idx = 0; idx <
ARRAY_LEN(self->stats.fixup_insert_left); ++idx) {
1748 prnt(where,
"Number of left insert fixups case %d: %d\n", idx + 1,
1749 self->stats.fixup_insert_left[idx]);
1751 for (idx = 0; idx <
ARRAY_LEN(self->stats.fixup_insert_right); ++idx) {
1752 prnt(where,
"Number of right insert fixups case %d: %d\n", idx + 1,
1753 self->stats.fixup_insert_right[idx]);
1756 for (idx = 0; idx <
ARRAY_LEN(self->stats.delete_children); ++idx) {
1757 prnt(where,
"Number of nodes deleted with %d children: %d\n", idx,
1758 self->stats.delete_children[idx]);
1760 for (idx = 0; idx <
ARRAY_LEN(self->stats.fixup_delete_left); ++idx) {
1761 prnt(where,
"Number of left delete fixups case %d: %d\n", idx + 1,
1762 self->stats.fixup_delete_left[idx]);
1764 for (idx = 0; idx <
ARRAY_LEN(self->stats.fixup_delete_right); ++idx) {
1765 prnt(where,
"Number of right delete fixups case %d: %d\n", idx + 1,
1766 self->stats.fixup_delete_right[idx]);
1771 #if defined(AO2_DEBUG) 1792 height_left = rb_check_black_height(node->
left);
1793 if (height_left < 0) {
1796 height_right = rb_check_black_height(node->
right);
1797 if (height_right < 0) {
1800 if (height_left != height_right) {
1802 "Tree node black height of children does not match! L:%d != R:%d\n",
1803 height_left, height_right);
1815 #if defined(AO2_DEBUG) 1854 if (self->root->parent) {
1855 if (self->root->parent == self->root) {
1862 if (self->root->is_red) {
1870 if (node->
left == node) {
1880 if (node->
right == node) {
1933 "Tree node is black and the red child does not have two children!\n");
1972 if (!res && rb_check_black_height(self->root) < 0) {
1980 ast_log(
LOG_ERROR,
"Total object count does not match ao2_container_count()!\n");
1985 if (count_node != self->common.nodes) {
1987 count_node, self->common.nodes);
2004 #
if defined(AO2_DEBUG)
2029 self->common.sort_fn =
sort_fn;
2030 self->common.cmp_fn =
cmp_fn;
2031 self->common.options =
options;
2042 const char *tag,
const char *
file,
int line,
const char *func)
2053 tag ?: __PRETTY_FUNCTION__, file, line, func);
static void rb_ao2_node_destructor(void *v_doomed)
static void rb_delete_fixup(struct ao2_container_rbtree *self, struct rbtree_node *child)
static struct rbtree_node * rb_node_pre(struct rbtree_node *node)
struct rbtree_node * root
struct ao2_container_node *(* ao2_iterator_next_fn)(struct ao2_container *self, struct ao2_container_node *prev, enum ao2_iterator_flags flags)
Find the next non-empty iteration node in the container.
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static struct rbtree_node * rb_node_next_full(struct rbtree_node *node)
static struct rbtree_node * rb_ao2_new_node(struct ao2_container_rbtree *self, void *obj_new, const char *tag, const char *file, int line, const char *func)
#define __is_ao2_object(user_data, file, line, func)
static void rb_rotate_right(struct ao2_container_rbtree *self, struct rbtree_node *node)
The arg parameter is a search key, but is not an object.
#define __container_unlink_node(node, flags)
void container_destruct(void *_c)
static struct rbtree_node * rb_node_post(struct rbtree_node *node)
Common, private definitions for astobj2.
Allow objects with duplicate keys in container.
struct rbtree_node * right
enum ao2_container_insert(* ao2_container_insert_fn)(struct ao2_container *self, struct ao2_container_node *node)
Insert a node into this container.
static void rb_insert_fixup(struct ao2_container_rbtree *self, struct rbtree_node *node)
void * __ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result
int() ao2_sort_fn(const void *obj_left, const void *obj_right, int flags)
Type of generic container sort function.
static struct rbtree_node * rb_find_initial(struct ao2_container_rbtree *self, void *obj_right, enum search_flags flags, enum equal_node_bias bias)
Assume that the ao2_container is already locked.
int(* ao2_container_integrity)(struct ao2_container *self)
Perform an integrity check on the specified container.
struct ao2_container common
Items common to all containers.
#define ao2_alloc_options(data_size, destructor_fn, options)
static const struct ao2_container_methods v_table_rbtree
ao2_container_find_first_fn traverse_first
search_flags
Flags passed to ao2_callback_fn(), ao2_hash_fn(), and ao2_sort_fn() to modify behaviour.
static struct rbtree_node * rb_node_next(struct rbtree_node *node)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Insert objects at the beginning of the container. (Otherwise it is the opposite; insert at the end...
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
#define is_ao2_object(user_data)
Traverse in ascending order (First to last container object)
int ao2_container_check(struct ao2_container *self, enum search_flags flags)
Perform an integrity check on the specified container.
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
static struct rbtree_node * rb_node_prev_full(struct rbtree_node *node)
struct ao2_container_node *(* ao2_container_find_first_fn)(struct ao2_container *self, enum search_flags flags, void *arg, void *v_state)
Find the first container node in a traversal.
The ao2 container objects with duplicate keys option field mask.
static struct ao2_container * rb_ao2_container_init(struct ao2_container_rbtree *self, unsigned int options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
Initialize a rbtree container.
static struct rbtree_node * rb_node_most_left(struct rbtree_node *node)
#define ao2_ref(o, delta)
struct rbtree_node * parent
#define AO2_DEVMODE_STAT(stat)
static struct rbtree_node * rb_ao2_find_next(struct ao2_container_rbtree *self, struct rbtree_traversal_state *state, struct rbtree_node *prev)
static void rb_delete_node(struct ao2_container_rbtree *self, struct rbtree_node *doomed)
static struct rbtree_node * rb_node_most_right(struct rbtree_node *node)
Traverse in descending order (Last to first container object)
static void rb_ao2_destroy(struct ao2_container_rbtree *self)
void(* ao2_container_destroy_fn)(struct ao2_container *self)
Destroy this container.
void(* ao2_container_statistics)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt)
Display statistics of the specified container.
ao2_iterator_next_fn iterator_next
Traverse in pre-order (Node then children, for tree container)
static struct rbtree_node * rb_node_prev(struct rbtree_node *node)
static struct rbtree_node * rb_ao2_find_first(struct ao2_container_rbtree *self, enum search_flags flags, void *arg, struct rbtree_traversal_state *state)
static enum empty_node_direction rb_find_empty_direction(struct rbtree_node *empty, ao2_sort_fn *sort_fn, void *obj_right, enum search_flags flags, enum equal_node_bias bias)
unsigned int destroying
TRUE if the container is being destroyed.
struct ao2_container * __ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, const char *tag, const char *file, int line, const char *func)
Prototypes for public functions only of internal interest,.
#define AO2_TRAVERSAL_STATE_SIZE
static struct ao2_container * rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self, const char *tag, const char *file, int line, const char *func)
struct ao2_container_node common
Items common to all container nodes.
The arg parameter is an object of the same type.
Replace objects with duplicate keys in container.
Traverse in post-order (Children then node, for tree container)
unsigned int ao2_options_get(void *obj)
Retrieve the ao2 options used to create the object.
static void rb_rotate_left(struct ao2_container_rbtree *self, struct rbtree_node *node)
Common, private definitions for astobj2 containers.
struct ao2_container *(* ao2_container_alloc_empty_clone_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func)
Create an empty copy of this container.
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
struct rbtree_node * left
Reject objects with duplicate keys in container.
Search option field mask.
void() ao2_prnt_obj_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Print object key.
struct ao2_container * my_container
static struct rbtree_node * rb_ao2_iterator_next(struct ao2_container_rbtree *self, struct rbtree_node *node, enum ao2_iterator_flags flags)
struct ao2_container_node *(* ao2_container_new_node_fn)(struct ao2_container *self, void *obj_new, const char *tag, const char *file, int line, const char *func)
Create a new container node.
ao2_container_alloc_empty_clone_fn alloc_empty_clone
Create an empty copy of this container.
Reject duplicate objects in container.
static enum ao2_container_insert rb_ao2_insert_node(struct ao2_container_rbtree *self, struct rbtree_node *node)
ao2_container_new_node_fn new_node
Traverse order option field mask.
struct ao2_container_node *(* ao2_container_find_next_fn)(struct ao2_container *self, void *v_state, struct ao2_container_node *prev)
Find the next container node in a traversal.
void(* ao2_container_display)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
Display contents of the specified container.