#include "asterisk.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
Go to the source code of this file.
Data Structures | |
struct | __priv_data |
struct | ao2_container |
struct | astobj2 |
struct | bucket |
struct | bucket_list |
Defines | |
#define | AO2_MAGIC 0xa570b123 |
#define | EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data) |
convert from a pointer _p to an astobj2 object | |
Functions | |
void * | __ao2_link (struct ao2_container *c, void *user_data, int iax2_hack) |
int | __ao2_lock (void *user_data, const char *file, const char *func, int line, const char *var) |
int | __ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var) |
int | __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var) |
void * | ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn) |
void | ao2_bt (void) |
void * | ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn cb_fn, void *arg) |
ao2_container * | ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn hash_fn, ao2_callback_fn cmp_fn) |
int | ao2_container_count (struct ao2_container *c) |
void * | ao2_find (struct ao2_container *c, void *arg, enum search_flags flags) |
void | ao2_iterator_destroy (struct ao2_iterator *i) |
Destroy a container iterator. | |
ao2_iterator | ao2_iterator_init (struct ao2_container *c, int flags) |
Create an iterator for a container. | |
void * | ao2_iterator_next (struct ao2_iterator *a) |
int | ao2_lock (void *user_data) |
int | ao2_match_by_addr (void *user_data, void *arg, int flags) |
another convenience function is a callback that matches on address | |
int | ao2_ref (void *user_data, const int delta) |
int | ao2_trylock (void *user_data) |
void * | ao2_unlink (struct ao2_container *c, void *user_data) |
int | ao2_unlock (void *user_data) |
int | astobj2_init (void) |
static int | cb_true (void *user_data, void *arg, int flags) |
special callback that matches all | |
static int | cd_cb (void *obj, void *arg, int flag) |
static void | container_destruct (void *c) |
static int | hash_zero (const void *user_obj, const int flags) |
always zero hash function | |
static struct astobj2 * | INTERNAL_OBJ (void *user_data) |
convert from a pointer _p to a user-defined object |
#define AO2_MAGIC 0xa570b123 |
#define EXTERNAL_OBJ | ( | _p | ) | ((_p) == NULL ? NULL : (_p)->user_data) |
convert from a pointer _p to an astobj2 object
Definition at line 126 of file astobj2.c.
Referenced by ao2_alloc(), and ao2_callback().
void* __ao2_link | ( | struct ao2_container * | c, | |
void * | user_data, | |||
int | iax2_hack | |||
) |
Definition at line 425 of file astobj2.c.
References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, bucket_list::entry, and INTERNAL_OBJ().
Referenced by set_config().
00426 { 00427 int i; 00428 /* create a new list entry */ 00429 struct bucket_list *p; 00430 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00431 00432 if (!obj) 00433 return NULL; 00434 00435 if (INTERNAL_OBJ(c) == NULL) 00436 return NULL; 00437 00438 p = ast_calloc(1, sizeof(*p)); 00439 if (!p) 00440 return NULL; 00441 00442 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00443 00444 ao2_lock(c); 00445 i %= c->n_buckets; 00446 p->astobj = obj; 00447 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00448 if (iax2_hack) 00449 AST_LIST_INSERT_HEAD(&c->buckets[i], p, entry); 00450 else 00451 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00452 ast_atomic_fetchadd_int(&c->elements, 1); 00453 ao2_ref(user_data, +1); 00454 ao2_unlock(c); 00455 00456 return p; 00457 }
int __ao2_lock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 149 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_lock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00150 { 00151 struct astobj2 *p = INTERNAL_OBJ(user_data); 00152 00153 if (p == NULL) 00154 return -1; 00155 00156 #ifdef AO2_DEBUG 00157 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00158 #endif 00159 00160 #ifndef DEBUG_THREADS 00161 return ast_mutex_lock(&p->priv_data.lock); 00162 #else 00163 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00164 #endif 00165 }
int __ao2_trylock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 186 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00187 { 00188 struct astobj2 *p = INTERNAL_OBJ(user_data); 00189 int res; 00190 00191 if (p == NULL) 00192 return -1; 00193 00194 #ifndef DEBUG_THREADS 00195 res = ast_mutex_trylock(&p->priv_data.lock); 00196 #else 00197 res = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00198 #endif 00199 00200 #ifdef AO2_DEBUG 00201 if (!res) { 00202 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00203 } 00204 #endif 00205 00206 return res; 00207 }
int __ao2_unlock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 223 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_unlock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00224 { 00225 struct astobj2 *p = INTERNAL_OBJ(user_data); 00226 00227 if (p == NULL) 00228 return -1; 00229 00230 #ifdef AO2_DEBUG 00231 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00232 #endif 00233 00234 #ifndef DEBUG_THREADS 00235 return ast_mutex_unlock(&p->priv_data.lock); 00236 #else 00237 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00238 #endif 00239 }
void* ao2_alloc | ( | size_t | data_size, | |
ao2_destructor_fn | destructor_fn | |||
) |
Definition at line 292 of file astobj2.c.
References AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), and EXTERNAL_OBJ.
Referenced by add_calltoken_ignore(), alloc_queue(), ao2_container_alloc(), ast_add_hint(), build_callno_limits(), build_peer(), build_user(), conf_run(), create_callno_pools(), create_queue_member(), get_filestream(), inprocess_count(), local_alloc(), moh_class_malloc(), new_iax(), peercnt_add(), update_provisional_keepalive(), and xml_translate().
00293 { 00294 /* allocation */ 00295 struct astobj2 *obj; 00296 00297 if (data_size < sizeof(void *)) 00298 data_size = sizeof(void *); 00299 00300 obj = ast_calloc(1, sizeof(*obj) + data_size); 00301 00302 if (obj == NULL) 00303 return NULL; 00304 00305 ast_mutex_init(&obj->priv_data.lock); 00306 obj->priv_data.magic = AO2_MAGIC; 00307 obj->priv_data.data_size = data_size; 00308 obj->priv_data.ref_counter = 1; 00309 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00310 00311 #ifdef AO2_DEBUG 00312 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00313 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00314 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00315 #endif 00316 00317 /* return a pointer to the user data */ 00318 return EXTERNAL_OBJ(obj); 00319 }
void* ao2_callback | ( | struct ao2_container * | c, | |
const enum search_flags | flags, | |||
ao2_callback_fn | cb_fn, | |||
void * | arg | |||
) |
Browse the container using different stategies accoding the flags.
Definition at line 494 of file astobj2.c.
References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), bucket_list::astobj, ao2_container::buckets, cb_true(), ao2_container::elements, bucket_list::entry, EXTERNAL_OBJ, free, ao2_container::hash_fn, INTERNAL_OBJ(), last, LOG_WARNING, match(), ao2_container::n_buckets, and ao2_container::version.
Referenced by admin_exec(), ao2_find(), ao2_unlink(), ast_moh_destroy(), calltoken_required(), conf_run(), container_destruct(), delete_users(), load_module(), load_moh_classes(), reload_config(), set_config_destroy(), set_peercnt_limit(), and unload_module().
00497 { 00498 int i, start, last; /* search boundaries */ 00499 void *ret = NULL; 00500 00501 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00502 return NULL; 00503 00504 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00505 ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); 00506 return NULL; 00507 } 00508 00509 /* override the match function if necessary */ 00510 #if 0 00511 /* Removing this slightly changes the meaning of OBJ_POINTER, but makes it 00512 * do what I want it to. I'd like to hint to ao2_callback that the arg is 00513 * of the same object type, so it can be passed to the hash function. 00514 * However, I don't want to imply that this is the object being searched for. */ 00515 if (flags & OBJ_POINTER) 00516 cb_fn = match_by_addr; 00517 else 00518 #endif 00519 if (cb_fn == NULL) /* if NULL, match everything */ 00520 cb_fn = cb_true; 00521 /* 00522 * XXX this can be optimized. 00523 * If we have a hash function and lookup by pointer, 00524 * run the hash function. Otherwise, scan the whole container 00525 * (this only for the time being. We need to optimize this.) 00526 */ 00527 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00528 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00529 else /* don't know, let's scan all buckets */ 00530 start = i = -1; /* XXX this must be fixed later. */ 00531 00532 /* determine the search boundaries: i..last-1 */ 00533 if (i < 0) { 00534 start = i = 0; 00535 last = c->n_buckets; 00536 } else if ((flags & OBJ_CONTINUE)) { 00537 last = c->n_buckets; 00538 } else { 00539 last = i + 1; 00540 } 00541 00542 ao2_lock(c); /* avoid modifications to the content */ 00543 00544 for (; i < last ; i++) { 00545 /* scan the list with prev-cur pointers */ 00546 struct bucket_list *cur; 00547 00548 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00549 int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP); 00550 00551 /* we found the object, performing operations according flags */ 00552 if (match == 0) { /* no match, no stop, continue */ 00553 continue; 00554 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00555 i = last; 00556 break; 00557 } 00558 /* we have a match (CMP_MATCH) here */ 00559 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00560 /* it is important to handle this case before the unlink */ 00561 ret = EXTERNAL_OBJ(cur->astobj); 00562 ao2_ref(ret, 1); 00563 } 00564 00565 if (flags & OBJ_UNLINK) { /* must unlink */ 00566 struct bucket_list *x = cur; 00567 00568 /* we are going to modify the container, so update version */ 00569 ast_atomic_fetchadd_int(&c->version, 1); 00570 AST_LIST_REMOVE_CURRENT(&c->buckets[i], entry); 00571 /* update number of elements and version */ 00572 ast_atomic_fetchadd_int(&c->elements, -1); 00573 ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00574 free(x); /* free the link record */ 00575 } 00576 00577 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00578 /* We found the only match we need */ 00579 i = last; /* force exit from outer loop */ 00580 break; 00581 } 00582 if (!(flags & OBJ_NODATA)) { 00583 #if 0 /* XXX to be completed */ 00584 /* 00585 * This is the multiple-return case. We need to link 00586 * the object in a list. The refcount is already increased. 00587 */ 00588 #endif 00589 } 00590 } 00591 AST_LIST_TRAVERSE_SAFE_END 00592 00593 if (ret) { 00594 /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ 00595 break; 00596 } 00597 00598 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00599 /* Move to the beginning to ensure we check every bucket */ 00600 i = -1; 00601 last = start; 00602 } 00603 } 00604 ao2_unlock(c); 00605 return ret; 00606 }
struct ao2_container* ao2_container_alloc | ( | const unsigned int | n_buckets, | |
ao2_hash_fn | hash_fn, | |||
ao2_callback_fn | cmp_fn | |||
) |
Definition at line 379 of file astobj2.c.
References ao2_alloc(), ast_atomic_fetchadd_int(), ao2_container::cmp_fn, container_destruct(), ao2_container::hash_fn, hash_zero(), ao2_container::n_buckets, and ao2_container::version.
Referenced by ast_pbx_init(), build_conf(), create_callno_pools(), init_queue(), load_module(), load_objects(), and xml_translate().
00381 { 00382 /* XXX maybe consistency check on arguments ? */ 00383 /* compute the container size */ 00384 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00385 00386 struct ao2_container *c = ao2_alloc(container_size, container_destruct); 00387 00388 if (!c) 00389 return NULL; 00390 00391 c->version = 1; /* 0 is a reserved value here */ 00392 c->n_buckets = n_buckets; 00393 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00394 c->cmp_fn = cmp_fn; 00395 00396 #ifdef AO2_DEBUG 00397 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00398 #endif 00399 00400 return c; 00401 }
int ao2_container_count | ( | struct ao2_container * | c | ) |
return the number of elements in the container
Definition at line 406 of file astobj2.c.
References ao2_container::elements.
Referenced by __queues_show(), get_unused_callno(), handle_show_hints(), and locals_show().
00407 { 00408 return c->elements; 00409 }
void* ao2_find | ( | struct ao2_container * | c, | |
void * | arg, | |||
enum search_flags | flags | |||
) |
the find function just invokes the default callback with some reasonable flags.
Definition at line 611 of file astobj2.c.
References ao2_callback(), and ao2_container::cmp_fn.
Referenced by __find_callno(), add_calltoken_ignore(), admin_exec(), ast_add_hint(), ast_change_hint(), ast_merge_contexts_and_delete(), ast_remove_hint(), authenticate_request(), authenticate_verify(), build_callno_limits(), build_peer(), build_user(), compare_weight(), conf_run(), find_peer(), find_user(), get_mohbyname(), get_unused_callno(), iax2_destroy_helper(), inprocess_count(), meetmemute(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), reload_queues(), remove_from_queue(), rt_handle_member_record(), sched_delay_remove(), and xml_translate().
00612 { 00613 return ao2_callback(c, flags, c->cmp_fn, arg); 00614 }
void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 634 of file astobj2.c.
References ao2_ref(), and ao2_iterator::c.
Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().
struct ao2_iterator ao2_iterator_init | ( | struct ao2_container * | c, | |
int | flags | |||
) |
Create an iterator for a container.
initialize an iterator so we start from the first object
Definition at line 619 of file astobj2.c.
References ao2_ref(), and ao2_iterator::flags.
Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().
00620 { 00621 struct ao2_iterator a = { 00622 .c = c, 00623 .flags = flags 00624 }; 00625 00626 ao2_ref(c, +1); 00627 00628 return a; 00629 }
void* ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 643 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, ao2_lock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, ao2_container::version, ao2_iterator::version, and bucket_list::version.
Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().
00644 { 00645 int lim; 00646 struct bucket_list *p = NULL; 00647 void *ret = NULL; 00648 00649 if (INTERNAL_OBJ(a->c) == NULL) 00650 return NULL; 00651 00652 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00653 ao2_lock(a->c); 00654 00655 /* optimization. If the container is unchanged and 00656 * we have a pointer, try follow it 00657 */ 00658 if (a->c->version == a->c_version && (p = a->obj) ) { 00659 if ( (p = AST_LIST_NEXT(p, entry)) ) 00660 goto found; 00661 /* nope, start from the next bucket */ 00662 a->bucket++; 00663 a->version = 0; 00664 a->obj = NULL; 00665 } 00666 00667 lim = a->c->n_buckets; 00668 00669 /* Browse the buckets array, moving to the next 00670 * buckets if we don't find the entry in the current one. 00671 * Stop when we find an element with version number greater 00672 * than the current one (we reset the version to 0 when we 00673 * switch buckets). 00674 */ 00675 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00676 /* scan the current bucket */ 00677 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00678 if (p->version > a->version) 00679 goto found; 00680 } 00681 } 00682 00683 found: 00684 if (p) { 00685 a->version = p->version; 00686 a->obj = p; 00687 a->c_version = a->c->version; 00688 ret = EXTERNAL_OBJ(p->astobj); 00689 /* inc refcount of returned object */ 00690 ao2_ref(ret, 1); 00691 } 00692 00693 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00694 ao2_unlock(a->c); 00695 00696 return ret; 00697 }
int ao2_lock | ( | void * | user_data | ) |
Definition at line 135 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_lock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __ao2_link(), __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), conf_run(), find_queue_by_name_rt(), get_member_status(), get_unused_callno(), inprocess_count(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), local_answer(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_write(), locals_show(), manager_queues_status(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_member_count(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), try_calling(), update_queue(), update_realtime_members(), and update_status().
00136 { 00137 struct astobj2 *p = INTERNAL_OBJ(user_data); 00138 00139 if (p == NULL) 00140 return -1; 00141 00142 #ifdef AO2_DEBUG 00143 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00144 #endif 00145 00146 return ast_mutex_lock(&p->priv_data.lock); 00147 }
int ao2_match_by_addr | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) |
another convenience function is a callback that matches on address
Definition at line 462 of file astobj2.c.
Referenced by ao2_unlink().
00463 { 00464 return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0; 00465 }
int ao2_ref | ( | void * | user_data, | |
const int | delta | |||
) |
Definition at line 244 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_log(), ast_mutex_destroy(), __priv_data::data_size, __priv_data::destructor_fn, free, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by __ao2_link(), __find_callno(), __queues_show(), __unload_module(), add_calltoken_ignore(), add_to_queue(), admin_exec(), announce_thread(), ao2_callback(), ao2_iterator_destroy(), ao2_iterator_init(), ast_add_hint(), ast_change_hint(), ast_closestream(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), build_conf(), calltoken_required(), cd_cb(), compare_weight(), complete_meetmecmd(), complete_queue_remove_member(), conf_free(), conf_queue_dtmf(), conf_run(), create_callno_pools(), destroy_queue(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), hangupcalls(), iax2_destroy(), iax2_show_callnumber_usage(), inprocess_count(), insert_entry(), interface_exists(), interface_exists_global(), load_module(), load_objects(), local_answer(), local_digit_begin(), local_digit_end(), local_hangup(), local_indicate(), local_request(), local_sendhtml(), local_sendtext(), local_write(), locals_show(), manager_queues_status(), meetme_cmd(), meetmemute(), new_iax(), num_available_members(), peer_ref(), peer_unref(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), peercnt_remove_cb(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), remove_from_queue(), remove_provisional_keepalive_sched(), remove_queue(), replace_callno(), rt_handle_member_record(), sched_delay_remove(), send_provisional_keepalive_full(), set_member_paused(), set_peercnt_limit(), try_calling(), unload_module(), unref_provisional_keepalive(), update_provisional_keepalive(), update_realtime_members(), update_status(), user_ref(), user_unref(), and xml_translate().
00245 { 00246 int current_value; 00247 int ret; 00248 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00249 00250 if (obj == NULL) 00251 return -1; 00252 00253 /* if delta is 0, just return the refcount */ 00254 if (delta == 0) 00255 return (obj->priv_data.ref_counter); 00256 00257 /* we modify with an atomic operation the reference counter */ 00258 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00259 current_value = ret + delta; 00260 00261 #ifdef AO2_DEBUG 00262 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00263 #endif 00264 00265 /* this case must never happen */ 00266 if (current_value < 0) 00267 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00268 00269 if (current_value <= 0) { /* last reference, destroy the object */ 00270 if (obj->priv_data.destructor_fn != NULL) 00271 obj->priv_data.destructor_fn(user_data); 00272 00273 ast_mutex_destroy(&obj->priv_data.lock); 00274 #ifdef AO2_DEBUG 00275 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00276 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00277 #endif 00278 /* for safety, zero-out the astobj2 header and also the 00279 * first word of the user-data, which we make sure is always 00280 * allocated. */ 00281 bzero(obj, sizeof(struct astobj2 *) + sizeof(void *) ); 00282 free(obj); 00283 } 00284 00285 return ret; 00286 }
int ao2_trylock | ( | void * | user_data | ) |
Definition at line 167 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by local_hangup(), local_queue_frame(), and local_setoption().
00168 { 00169 struct astobj2 *p = INTERNAL_OBJ(user_data); 00170 int res; 00171 00172 if (p == NULL) 00173 return -1; 00174 00175 res = ast_mutex_trylock(&p->priv_data.lock); 00176 00177 #ifdef AO2_DEBUG 00178 if (!res) { 00179 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00180 } 00181 #endif 00182 00183 return res; 00184 }
void* ao2_unlink | ( | struct ao2_container * | c, | |
void * | user_data | |||
) |
Definition at line 471 of file astobj2.c.
References ao2_callback(), ao2_match_by_addr(), and INTERNAL_OBJ().
Referenced by ast_remove_hint(), build_user(), free_members(), iax2_prune_realtime(), local_hangup(), local_request(), peercnt_remove(), prune_users(), reload_queues(), remove_by_peercallno(), remove_by_transfercallno(), remove_from_queue(), unlink_peer(), and update_realtime_members().
00472 { 00473 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00474 return NULL; 00475 00476 ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00477 00478 return NULL; 00479 }
int ao2_unlock | ( | void * | user_data | ) |
Definition at line 209 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_unlock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __ao2_link(), __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), conf_run(), find_queue_by_name_rt(), get_member_status(), get_unused_callno(), inprocess_count(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), local_answer(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_setoption(), local_write(), locals_show(), manager_queues_status(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_member_count(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), try_calling(), update_queue(), update_realtime_members(), and update_status().
00210 { 00211 struct astobj2 *p = INTERNAL_OBJ(user_data); 00212 00213 if (p == NULL) 00214 return -1; 00215 00216 #ifdef AO2_DEBUG 00217 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00218 #endif 00219 00220 return ast_mutex_unlock(&p->priv_data.lock); 00221 }
int astobj2_init | ( | void | ) |
Definition at line 837 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
00838 { 00839 #ifdef AO2_DEBUG 00840 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 00841 #endif 00842 00843 return 0; 00844 }
static int cb_true | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
special callback that matches all
Definition at line 484 of file astobj2.c.
Referenced by ao2_callback().
static int cd_cb | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 702 of file astobj2.c.
References ao2_ref().
Referenced by container_destruct().
00703 { 00704 ao2_ref(obj, -1); 00705 return 0; 00706 }
static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 708 of file astobj2.c.
References ao2_callback(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_list::entry, and ao2_container::n_buckets.
Referenced by ao2_container_alloc().
00709 { 00710 struct ao2_container *c = _c; 00711 int i; 00712 00713 ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00714 00715 for (i = 0; i < c->n_buckets; i++) { 00716 struct bucket_list *cur; 00717 00718 while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00719 ast_free(cur); 00720 } 00721 } 00722 00723 #ifdef AO2_DEBUG 00724 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00725 #endif 00726 }
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.
Definition at line 370 of file astobj2.c.
Referenced by ao2_container_alloc().
static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [inline, static] |
convert from a pointer _p to a user-defined object
Definition at line 103 of file astobj2.c.
References AO2_MAGIC, ast_log(), and LOG_ERROR.
Referenced by __ao2_link(), __ao2_lock(), __ao2_trylock(), __ao2_unlock(), ao2_callback(), ao2_iterator_next(), ao2_lock(), ao2_ref(), ao2_trylock(), ao2_unlink(), and ao2_unlock().
00104 { 00105 struct astobj2 *p; 00106 00107 if (!user_data) { 00108 ast_log(LOG_ERROR, "user_data is NULL\n"); 00109 return NULL; 00110 } 00111 00112 p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); 00113 if (AO2_MAGIC != (p->priv_data.magic) ) { 00114 ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p); 00115 p = NULL; 00116 } 00117 00118 return p; 00119 }