Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Functions | Variables
astobj2_hash.c File Reference

Hash table functions implementing astobj2 containers. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "astobj2_private.h"
#include "astobj2_container_private.h"
#include "asterisk/dlinkedlists.h"
#include "asterisk/utils.h"
Include dependency graph for astobj2_hash.c:

Go to the source code of this file.

Data Structures

struct  ao2_container_hash
 
struct  hash_bucket
 
struct  hash_bucket_node
 
struct  hash_traversal_state
 
struct  hash_traversal_state_check
 

Functions

struct ao2_container__ao2_container_alloc_hash (unsigned int ao2_options, unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, const char *tag, const char *file, int line, const char *func)
 
struct ao2_container__ao2_container_alloc_list (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)
 
static struct ao2_containerhash_ao2_alloc_empty_clone (struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func)
 
static struct ao2_containerhash_ao2_container_init (struct ao2_container_hash *self, unsigned int options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
 Initialize a hash container with the desired number of buckets. More...
 
static void hash_ao2_destroy (struct ao2_container_hash *self)
 
static struct hash_bucket_nodehash_ao2_find_first (struct ao2_container_hash *self, enum search_flags flags, void *arg, struct hash_traversal_state *state)
 
static struct hash_bucket_nodehash_ao2_find_next (struct ao2_container_hash *self, struct hash_traversal_state *state, struct hash_bucket_node *prev)
 
static enum ao2_container_insert hash_ao2_insert_node (struct ao2_container_hash *self, struct hash_bucket_node *node)
 
static struct hash_bucket_nodehash_ao2_iterator_next (struct ao2_container_hash *self, struct hash_bucket_node *node, enum ao2_iterator_flags flags)
 
static struct hash_bucket_nodehash_ao2_new_node (struct ao2_container_hash *self, void *obj_new, const char *tag, const char *file, int line, const char *func)
 
static void hash_ao2_node_destructor (void *v_doomed)
 
static int hash_zero (const void *user_obj, const int flags)
 always zero hash function More...
 

Variables

static const struct ao2_container_methods v_table_hash
 

Detailed Description

Hash table functions implementing astobj2 containers.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file astobj2_hash.c.

Function Documentation

◆ __ao2_container_alloc_hash()

struct ao2_container * __ao2_container_alloc_hash ( unsigned int  ao2_options,
unsigned int  container_options,
unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_sort_fn sort_fn,
ao2_callback_fn cmp_fn,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 1067 of file astobj2_hash.c.

1071{
1072 unsigned int num_buckets;
1073 size_t container_size;
1074 struct ao2_container_hash *self;
1075
1076 num_buckets = hash_fn ? n_buckets : 1;
1077 container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
1078
1079 self = __ao2_alloc(container_size, container_destruct, ao2_options,
1080 tag ?: __PRETTY_FUNCTION__, file, line, func);
1081 return hash_ao2_container_init(self, container_options, num_buckets, hash_fn,
1082 sort_fn, cmp_fn);
1083}
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
Definition: astobj2.c:768
void container_destruct(void *_c)
static struct ao2_container * hash_ao2_container_init(struct ao2_container_hash *self, unsigned int options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
Initialize a hash container with the desired number of buckets.
ao2_hash_fn * hash_fn
Definition: astobj2_hash.c:71

References __ao2_alloc(), container_destruct(), make_ari_stubs::file, hash_ao2_container_init(), ao2_container_hash::hash_fn, and ao2_container_hash::n_buckets.

Referenced by __ao2_container_alloc_list(), and hash_ao2_alloc_empty_clone().

◆ __ao2_container_alloc_list()

struct ao2_container * __ao2_container_alloc_list ( 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 
)

Definition at line 1085 of file astobj2_hash.c.

1088{
1089 return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL,
1090 sort_fn, cmp_fn, tag, file, line, func);
1091}
struct ao2_container * __ao2_container_alloc_hash(unsigned int ao2_options, unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, const char *tag, const char *file, int line, const char *func)
#define NULL
Definition: resample.c:96

References __ao2_container_alloc_hash(), ao2_container::cmp_fn, make_ari_stubs::file, NULL, and ao2_container::sort_fn.

◆ hash_ao2_alloc_empty_clone()

static struct ao2_container * hash_ao2_alloc_empty_clone ( struct ao2_container_hash self,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)
static

Definition at line 116 of file astobj2_hash.c.

118{
119 if (!__is_ao2_object(self, file, line, func)) {
120 return NULL;
121 }
122
124 self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
125 tag, file, line, func);
126}
unsigned int ao2_options_get(void *obj)
Retrieve the ao2 options used to create the object.
Definition: astobj2.c:781
#define __is_ao2_object(user_data, file, line, func)
struct ao2_container common
Items common to all containers.
Definition: astobj2_hash.c:70
ao2_callback_fn * cmp_fn

References __ao2_container_alloc_hash(), __is_ao2_object, ao2_options_get(), ao2_container::cmp_fn, ao2_container_hash::common, make_ari_stubs::file, ao2_container_hash::hash_fn, ao2_container_hash::n_buckets, NULL, ao2_container::options, and ao2_container::sort_fn.

◆ hash_ao2_container_init()

static struct ao2_container * hash_ao2_container_init ( struct ao2_container_hash self,
unsigned int  options,
unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_sort_fn sort_fn,
ao2_callback_fn cmp_fn 
)
static

Initialize a hash container with the desired number of buckets.

Parameters
selfContainer to initialize.
optionsContainer behaviour options (See enum ao2_container_opts)
n_bucketsNumber of buckets for hash
hash_fnPointer to a function computing a hash value.
sort_fnPointer to a sort function.
cmp_fnPointer to a compare function used by ao2_find.
Returns
A pointer to a struct container.

Definition at line 1045 of file astobj2_hash.c.

1048{
1049 if (!self) {
1050 return NULL;
1051 }
1052
1053 self->common.v_table = &v_table_hash;
1054 self->common.sort_fn = sort_fn;
1055 self->common.cmp_fn = cmp_fn;
1056 self->common.options = options;
1057 self->hash_fn = hash_fn ? hash_fn : hash_zero;
1058 self->n_buckets = n_buckets;
1059
1060#ifdef AO2_DEBUG
1061 ast_atomic_fetchadd_int(&ao2.total_containers, 1);
1062#endif /* defined(AO2_DEBUG) */
1063
1064 return (struct ao2_container *) self;
1065}
static int hash_zero(const void *user_obj, const int flags)
always zero hash function
static const struct ao2_container_methods v_table_hash
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
Generic container type.
const struct ao2_container_methods * v_table
static struct test_options options

References ast_atomic_fetchadd_int(), ao2_container::cmp_fn, ao2_container_hash::common, ao2_container_hash::hash_fn, hash_zero(), ao2_container_hash::n_buckets, NULL, ao2_container::options, options, ao2_container::sort_fn, ao2_container::v_table, and v_table_hash.

Referenced by __ao2_container_alloc_hash().

◆ hash_ao2_destroy()

static void hash_ao2_destroy ( struct ao2_container_hash self)
static

Definition at line 731 of file astobj2_hash.c.

732{
733 int idx;
734
735 /* Check that the container no longer has any nodes */
736 for (idx = self->n_buckets; idx--;) {
737 if (!AST_DLLIST_EMPTY(&self->buckets[idx].list)) {
738 ast_log(LOG_ERROR, "Node ref leak. Hash container still has nodes!\n");
739 ast_assert(0);
740 break;
741 }
742 }
743}
#define ast_log
Definition: astobj2.c:42
#define AST_DLLIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: dlinkedlists.h:469
#define LOG_ERROR
struct hash_bucket buckets[0]
Definition: astobj2_hash.c:75
struct hash_bucket::@301 list
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, AST_DLLIST_EMPTY, ast_log, ao2_container_hash::buckets, hash_bucket::list, LOG_ERROR, and ao2_container_hash::n_buckets.

◆ hash_ao2_find_first()

static struct hash_bucket_node * hash_ao2_find_first ( struct ao2_container_hash self,
enum search_flags  flags,
void *  arg,
struct hash_traversal_state state 
)
static

Definition at line 333 of file astobj2_hash.c.

334{
335 struct hash_bucket_node *node;
336 int bucket_cur;
337 int cmp;
338
339 memset(state, 0, sizeof(*state));
340 state->arg = arg;
341 state->flags = flags;
342
343 /* Determine traversal order. */
344 switch (flags & OBJ_ORDER_MASK) {
345 case OBJ_ORDER_POST:
347 state->descending = 1;
348 break;
349 case OBJ_ORDER_PRE:
351 default:
352 break;
353 }
354
355 /*
356 * If lookup by pointer or search key, run the hash and optional
357 * sort functions. Otherwise, traverse the whole container.
358 */
359 switch (flags & OBJ_SEARCH_MASK) {
361 case OBJ_SEARCH_KEY:
362 /* we know hash can handle this case */
363 bucket_cur = abs(self->hash_fn(arg, flags & OBJ_SEARCH_MASK)
364 % self->n_buckets);
365 state->sort_fn = self->common.sort_fn;
366 break;
368 /* scan all buckets for partial key matches */
369 bucket_cur = -1;
370 state->sort_fn = self->common.sort_fn;
371 break;
372 default:
373 /* don't know, let's scan all buckets */
374 bucket_cur = -1;
375 state->sort_fn = NULL;
376 break;
377 }
378
379 if (state->descending) {
380 /*
381 * Determine the search boundaries of a descending traversal.
382 *
383 * bucket_cur downto state->bucket_last
384 */
385 if (bucket_cur < 0) {
386 bucket_cur = self->n_buckets - 1;
387 state->bucket_last = 0;
388 } else {
389 state->bucket_last = bucket_cur;
390 }
391 state->bucket_start = bucket_cur;
392
393 /* For each bucket */
394 for (; state->bucket_last <= bucket_cur; --bucket_cur) {
395 /* For each node in the bucket. */
396 for (node = AST_DLLIST_LAST(&self->buckets[bucket_cur].list);
397 node;
399 if (!node->common.obj) {
400 /* Node is empty */
401 continue;
402 }
403
404 if (state->sort_fn) {
405 /* Filter node through the sort_fn */
406 cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
407 if (cmp > 0) {
408 continue;
409 }
410 if (cmp < 0) {
411 /* No more nodes in this bucket are possible to match. */
412 break;
413 }
414 }
415
416 /* We have the first traversal node */
417 ao2_ref(node, +1);
418 return node;
419 }
420 }
421 } else {
422 /*
423 * Determine the search boundaries of an ascending traversal.
424 *
425 * bucket_cur to state->bucket_last-1
426 */
427 if (bucket_cur < 0) {
428 bucket_cur = 0;
429 state->bucket_last = self->n_buckets;
430 } else {
431 state->bucket_last = bucket_cur + 1;
432 }
433 state->bucket_start = bucket_cur;
434
435 /* For each bucket */
436 for (; bucket_cur < state->bucket_last; ++bucket_cur) {
437 /* For each node in the bucket. */
438 for (node = AST_DLLIST_FIRST(&self->buckets[bucket_cur].list);
439 node;
441 if (!node->common.obj) {
442 /* Node is empty */
443 continue;
444 }
445
446 if (state->sort_fn) {
447 /* Filter node through the sort_fn */
448 cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
449 if (cmp < 0) {
450 continue;
451 }
452 if (cmp > 0) {
453 /* No more nodes in this bucket are possible to match. */
454 break;
455 }
456 }
457
458 /* We have the first traversal node */
459 ao2_ref(node, +1);
460 return node;
461 }
462 }
463 }
464
465 return NULL;
466}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ OBJ_ORDER_MASK
Traverse order option field mask.
Definition: astobj2.h:1119
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_ORDER_DESCENDING
Traverse in descending order (Last to first container object)
Definition: astobj2.h:1123
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_ORDER_PRE
Traverse in pre-order (Node then children, for tree container)
Definition: astobj2.h:1132
@ OBJ_ORDER_ASCENDING
Traverse in ascending order (First to last container object)
Definition: astobj2.h:1121
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_ORDER_POST
Traverse in post-order (Children then node, for tree container)
Definition: astobj2.h:1141
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define AST_DLLIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: dlinkedlists.h:446
#define AST_DLLIST_PREV(elm, field)
Returns the previous entry in the list before the given entry.
Definition: dlinkedlists.h:457
#define AST_DLLIST_FIRST(head)
Returns the first entry contained in a list.
Definition: dlinkedlists.h:422
#define AST_DLLIST_LAST(head)
Returns the last entry contained in a list.
Definition: dlinkedlists.h:431
#define abs(x)
Definition: f2c.h:195
struct hash_bucket_node::@300 links
Definition: test_heap.c:38

References abs, ao2_ref, AST_DLLIST_FIRST, AST_DLLIST_LAST, AST_DLLIST_NEXT, AST_DLLIST_PREV, ao2_container_hash::buckets, ao2_container_hash::common, ao2_container_hash::hash_fn, hash_bucket_node::links, hash_bucket::list, ao2_container_hash::n_buckets, NULL, OBJ_ORDER_ASCENDING, OBJ_ORDER_DESCENDING, OBJ_ORDER_MASK, OBJ_ORDER_POST, OBJ_ORDER_PRE, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and ao2_container::sort_fn.

◆ hash_ao2_find_next()

static struct hash_bucket_node * hash_ao2_find_next ( struct ao2_container_hash self,
struct hash_traversal_state state,
struct hash_bucket_node prev 
)
static

Definition at line 481 of file astobj2_hash.c.

482{
483 struct hash_bucket_node *node;
484 void *arg;
485 enum search_flags flags;
486 int bucket_cur;
487 int cmp;
488
489 arg = state->arg;
490 flags = state->flags;
491 bucket_cur = prev->my_bucket;
492 node = prev;
493
494 /*
495 * This function is structured the same as hash_ao2_find_first()
496 * intentionally. We are resuming the search loops from
497 * hash_ao2_find_first() in order to find the next node. The
498 * search loops must be resumed where hash_ao2_find_first()
499 * returned with the first node.
500 */
501 if (state->descending) {
502 goto hash_descending_resume;
503
504 /* For each bucket */
505 for (; state->bucket_last <= bucket_cur; --bucket_cur) {
506 /* For each node in the bucket. */
507 for (node = AST_DLLIST_LAST(&self->buckets[bucket_cur].list);
508 node;
510 if (!node->common.obj) {
511 /* Node is empty */
512 continue;
513 }
514
515 if (state->sort_fn) {
516 /* Filter node through the sort_fn */
517 cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
518 if (cmp > 0) {
519 continue;
520 }
521 if (cmp < 0) {
522 /* No more nodes in this bucket are possible to match. */
523 break;
524 }
525 }
526
527 /* We have the next traversal node */
528 ao2_ref(node, +1);
529
530 /*
531 * Dereferencing the prev node may result in our next node
532 * object being removed by another thread. This could happen if
533 * the container uses RW locks and the container was read
534 * locked.
535 */
536 ao2_ref(prev, -1);
537 if (node->common.obj) {
538 return node;
539 }
540 prev = node;
541
542hash_descending_resume:;
543 }
544 }
545 } else {
546 goto hash_ascending_resume;
547
548 /* For each bucket */
549 for (; bucket_cur < state->bucket_last; ++bucket_cur) {
550 /* For each node in the bucket. */
551 for (node = AST_DLLIST_FIRST(&self->buckets[bucket_cur].list);
552 node;
554 if (!node->common.obj) {
555 /* Node is empty */
556 continue;
557 }
558
559 if (state->sort_fn) {
560 /* Filter node through the sort_fn */
561 cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
562 if (cmp < 0) {
563 continue;
564 }
565 if (cmp > 0) {
566 /* No more nodes in this bucket are possible to match. */
567 break;
568 }
569 }
570
571 /* We have the next traversal node */
572 ao2_ref(node, +1);
573
574 /*
575 * Dereferencing the prev node may result in our next node
576 * object being removed by another thread. This could happen if
577 * the container uses RW locks and the container was read
578 * locked.
579 */
580 ao2_ref(prev, -1);
581 if (node->common.obj) {
582 return node;
583 }
584 prev = node;
585
586hash_ascending_resume:;
587 }
588 }
589 }
590
591 /* No more nodes in the container left to traverse. */
592 ao2_ref(prev, -1);
593 return NULL;
594}
search_flags
Flags passed to ao2_callback_fn(), ao2_hash_fn(), and ao2_sort_fn() to modify behaviour.
Definition: astobj2.h:1034

References ao2_ref, AST_DLLIST_FIRST, AST_DLLIST_LAST, AST_DLLIST_NEXT, AST_DLLIST_PREV, ao2_container_hash::buckets, hash_bucket_node::links, hash_bucket::list, hash_bucket_node::my_bucket, NULL, and OBJ_SEARCH_MASK.

◆ hash_ao2_insert_node()

static enum ao2_container_insert hash_ao2_insert_node ( struct ao2_container_hash self,
struct hash_bucket_node node 
)
static

Definition at line 237 of file astobj2_hash.c.

239{
240 int cmp;
241 struct hash_bucket *bucket;
242 struct hash_bucket_node *cur;
243 ao2_sort_fn *sort_fn;
244 uint32_t options;
245
246 bucket = &self->buckets[node->my_bucket];
247 sort_fn = self->common.sort_fn;
248 options = self->common.options;
249
251 if (sort_fn) {
253 cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
254 if (cmp > 0) {
255 continue;
256 }
257 if (cmp < 0) {
260 }
262 default:
264 break;
266 /* Reject all objects with the same key. */
269 if (cur->common.obj == node->common.obj) {
270 /* Reject inserting the same object */
272 }
273 break;
275 SWAP(cur->common.obj, node->common.obj);
276 ao2_ref(node, -1);
278 }
279 }
281 }
283 } else {
284 if (sort_fn) {
286 cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
287 if (cmp < 0) {
288 continue;
289 }
290 if (cmp > 0) {
293 }
295 default:
297 break;
299 /* Reject all objects with the same key. */
302 if (cur->common.obj == node->common.obj) {
303 /* Reject inserting the same object */
305 }
306 break;
308 SWAP(cur->common.obj, node->common.obj);
309 ao2_ref(node, -1);
311 }
312 }
314 }
316 }
318}
int() ao2_sort_fn(const void *obj_left, const void *obj_right, int flags)
Type of generic container sort function.
Definition: astobj2.h:1276
@ AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT
Reject duplicate objects in container.
Definition: astobj2.h:1201
@ AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN
Insert objects at the beginning of the container. (Otherwise it is the opposite; insert at the end....
Definition: astobj2.h:1172
@ AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW
Allow objects with duplicate keys in container.
Definition: astobj2.h:1181
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
@ AO2_CONTAINER_ALLOC_OPT_DUPS_MASK
The ao2 container objects with duplicate keys option field mask.
Definition: astobj2.h:1177
@ AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED
@ AO2_CONTAINER_INSERT_NODE_REJECTED
@ AO2_CONTAINER_INSERT_NODE_INSERTED
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: dlinkedlists.h:888
#define AST_DLLIST_INSERT_AFTER_CURRENT(elm, field)
Inserts a list node after the current node during a traversal.
Definition: dlinkedlists.h:723
#define AST_DLLIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: dlinkedlists.h:849
#define AST_DLLIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list node before the current node during a traversal.
Definition: dlinkedlists.h:696
#define AST_DLLIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_DLLIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END
Closes a safe loop traversal block.
Definition: dlinkedlists.h:921
#define AST_DLLIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: dlinkedlists.h:913
struct ao2_container_node common
Items common to all container nodes.
Definition: astobj2_hash.c:42
#define SWAP(a, b)
Definition: utils.h:235

References AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW, AO2_CONTAINER_ALLOC_OPT_DUPS_MASK, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN, AO2_CONTAINER_INSERT_NODE_INSERTED, AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED, AO2_CONTAINER_INSERT_NODE_REJECTED, ao2_ref, AST_DLLIST_INSERT_AFTER_CURRENT, AST_DLLIST_INSERT_BEFORE_CURRENT, AST_DLLIST_INSERT_HEAD, AST_DLLIST_INSERT_TAIL, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN, AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END, AST_DLLIST_TRAVERSE_SAFE_BEGIN, AST_DLLIST_TRAVERSE_SAFE_END, ao2_container_hash::buckets, hash_bucket_node::common, ao2_container_hash::common, hash_bucket_node::links, hash_bucket::list, ao2_container_node::obj, OBJ_SEARCH_OBJECT, ao2_container::options, options, ao2_container::sort_fn, and SWAP.

◆ hash_ao2_iterator_next()

static struct hash_bucket_node * hash_ao2_iterator_next ( struct ao2_container_hash self,
struct hash_bucket_node node,
enum ao2_iterator_flags  flags 
)
static

Definition at line 611 of file astobj2_hash.c.

612{
613 int cur_bucket;
614
615 if (flags & AO2_ITERATOR_DESCENDING) {
616 if (node) {
617 cur_bucket = node->my_bucket;
618
619 /* Find next non-empty node. */
620 for (;;) {
621 node = AST_DLLIST_PREV(node, links);
622 if (!node) {
623 break;
624 }
625 if (node->common.obj) {
626 /* Found a non-empty node. */
627 return node;
628 }
629 }
630 } else {
631 /* Find first non-empty node. */
632 cur_bucket = self->n_buckets;
633 }
634
635 /* Find a non-empty node in the remaining buckets */
636 while (0 <= --cur_bucket) {
637 node = AST_DLLIST_LAST(&self->buckets[cur_bucket].list);
638 while (node) {
639 if (node->common.obj) {
640 /* Found a non-empty node. */
641 return node;
642 }
643 node = AST_DLLIST_PREV(node, links);
644 }
645 }
646 } else {
647 if (node) {
648 cur_bucket = node->my_bucket;
649
650 /* Find next non-empty node. */
651 for (;;) {
652 node = AST_DLLIST_NEXT(node, links);
653 if (!node) {
654 break;
655 }
656 if (node->common.obj) {
657 /* Found a non-empty node. */
658 return node;
659 }
660 }
661 } else {
662 /* Find first non-empty node. */
663 cur_bucket = -1;
664 }
665
666 /* Find a non-empty node in the remaining buckets */
667 while (++cur_bucket < self->n_buckets) {
668 node = AST_DLLIST_FIRST(&self->buckets[cur_bucket].list);
669 while (node) {
670 if (node->common.obj) {
671 /* Found a non-empty node. */
672 return node;
673 }
674 node = AST_DLLIST_NEXT(node, links);
675 }
676 }
677 }
678
679 /* No more nodes to visit in the container. */
680 return NULL;
681}
@ AO2_ITERATOR_DESCENDING
Definition: astobj2.h:1875

References AO2_ITERATOR_DESCENDING, AST_DLLIST_FIRST, AST_DLLIST_LAST, AST_DLLIST_NEXT, AST_DLLIST_PREV, ao2_container_hash::buckets, hash_bucket_node::links, hash_bucket::list, ao2_container_hash::n_buckets, and NULL.

◆ hash_ao2_new_node()

static struct hash_bucket_node * hash_ao2_new_node ( struct ao2_container_hash self,
void *  obj_new,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)
static

Definition at line 206 of file astobj2_hash.c.

207{
208 struct hash_bucket_node *node;
209 int i;
210
213 if (!node) {
214 return NULL;
215 }
216
217 i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT) % self->n_buckets);
218
219 __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func);
220 node->common.obj = obj_new;
221 node->common.my_container = (struct ao2_container *) self;
222 node->my_bucket = i;
223
224 return node;
225}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_NO_REF_DEBUG
Definition: astobj2.h:378
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:498
static void hash_ao2_node_destructor(void *v_doomed)
Definition: astobj2_hash.c:143

References __ao2_ref(), abs, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_NO_REF_DEBUG, ao2_alloc_options, make_ari_stubs::file, hash_ao2_node_destructor(), ao2_container_hash::hash_fn, ao2_container_hash::n_buckets, NULL, and OBJ_SEARCH_OBJECT.

◆ hash_ao2_node_destructor()

static void hash_ao2_node_destructor ( void *  v_doomed)
static

Definition at line 143 of file astobj2_hash.c.

144{
145 struct hash_bucket_node *doomed = v_doomed;
146
147 if (doomed->common.is_linked) {
148 struct ao2_container_hash *my_container;
149 struct hash_bucket *bucket;
150
151 /*
152 * Promote to write lock if not already there. Since
153 * adjust_lock() can potentially release and block waiting for a
154 * write lock, care must be taken to ensure that node references
155 * are released before releasing the container references.
156 *
157 * Node references held by an iterator can only be held while
158 * the iterator also holds a reference to the container. These
159 * node references must be unreferenced before the container can
160 * be unreferenced to ensure that the node will not get a
161 * negative reference and the destructor called twice for the
162 * same node.
163 */
164 my_container = (struct ao2_container_hash *) doomed->common.my_container;
165#ifdef AST_DEVMODE
166 is_ao2_object(my_container);
167#endif
168
169 __adjust_lock(my_container, AO2_LOCK_REQ_WRLOCK, 1);
170
171#if defined(AO2_DEBUG)
172 if (!my_container->common.destroying
174 ast_log(LOG_ERROR, "Container integrity failed before node deletion.\n");
175 }
176#endif /* defined(AO2_DEBUG) */
177 bucket = &my_container->buckets[doomed->my_bucket];
178 AST_DLLIST_REMOVE(&bucket->list, doomed, links);
179 AO2_DEVMODE_STAT(--my_container->common.nodes);
180 }
181
182 /*
183 * We could have an object in the node if the container is being
184 * destroyed or the node had not been linked in yet.
185 */
186 if (doomed->common.obj) {
188 }
189}
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
Definition: astobj2.c:425
int ao2_container_check(struct ao2_container *self, enum search_flags flags)
Perform an integrity check on the specified container.
@ AO2_LOCK_REQ_WRLOCK
Definition: astobj2.h:706
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define __container_unlink_node(node, flags)
@ AO2_UNLINK_NODE_UNLINK_OBJECT
#define is_ao2_object(user_data)
#define AO2_DEVMODE_STAT(stat)
#define AST_DLLIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
struct ao2_container * my_container
unsigned int destroying
TRUE if the container is being destroyed.

References __adjust_lock(), __container_unlink_node, ao2_container_check(), AO2_DEVMODE_STAT, AO2_LOCK_REQ_WRLOCK, AO2_UNLINK_NODE_UNLINK_OBJECT, AST_DLLIST_REMOVE, ast_log, ao2_container_hash::buckets, hash_bucket_node::common, ao2_container_hash::common, ao2_container::destroying, is_ao2_object, ao2_container_node::is_linked, hash_bucket::list, LOG_ERROR, hash_bucket_node::my_bucket, ao2_container_node::my_container, ao2_container_node::obj, and OBJ_NOLOCK.

Referenced by hash_ao2_new_node().

◆ hash_zero()

static int hash_zero ( const void *  user_obj,
const int  flags 
)
static

always zero hash function

it is convenient to have a hash function that always returns 0. This is basically used when we want to have a container that is a simple linked list.

Return values
0

Definition at line 1028 of file astobj2_hash.c.

1029{
1030 return 0;
1031}

Referenced by hash_ao2_container_init().

Variable Documentation

◆ v_table_hash

const struct ao2_container_methods v_table_hash
static

Hash container virtual method table.

Definition at line 1002 of file astobj2_hash.c.

Referenced by hash_ao2_container_init().