#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include <execinfo.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 | |
#define | N1 20 |
Functions | |
void * | ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn) |
Allocate and initialize an object. | |
void | ao2_bt (void) |
void * | ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg) |
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below. | |
ao2_container * | ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
Allocate and initialize a container with the desired number of buckets. | |
int | ao2_container_count (struct ao2_container *c) |
Returns the number of elements in a container. | |
void * | ao2_find (struct ao2_container *c, void *arg, enum search_flags flags) |
ao2_iterator | ao2_iterator_init (struct ao2_container *c, int flags) |
void * | ao2_iterator_next (struct ao2_iterator *a) |
void * | ao2_link (struct ao2_container *c, void *user_data) |
Add an object to a container. | |
int | ao2_lock (void *user_data) |
Lock an object. | |
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) |
Reference/unreference an object and return the old refcount. | |
int | ao2_trylock (void *user_data) |
Try locking-- (don't block if fail). | |
void * | ao2_unlink (struct ao2_container *c, void *user_data) |
Remove an object from the container. | |
int | ao2_unlock (void *user_data) |
Unlock an object. | |
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 127 of file astobj2.c.
Referenced by ao2_alloc(), and ao2_callback().
#define N1 20 |
Referenced by ao2_bt().
void* ao2_alloc | ( | const size_t | data_size, | |
ao2_destructor_fn | destructor_fn | |||
) |
Allocate and initialize an object.
data_size | The sizeof() of the user-defined structure. | |
destructor_fn | The destructor function (can be NULL) |
Definition at line 248 of file astobj2.c.
References AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), and EXTERNAL_OBJ.
Referenced by alloc_queue(), ao2_container_alloc(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_device(), build_peer(), build_profile(), build_route(), build_user(), conf_run(), create_queue_member(), dialgroup_write(), get_filestream(), moh_class_malloc(), new_iax(), set_fn(), and xml_translate().
00249 { 00250 /* allocation */ 00251 struct astobj2 *obj; 00252 00253 if (data_size < sizeof(void *)) 00254 data_size = sizeof(void *); 00255 00256 obj = ast_calloc(1, sizeof(*obj) + data_size); 00257 00258 if (obj == NULL) 00259 return NULL; 00260 00261 ast_mutex_init(&obj->priv_data.lock); 00262 obj->priv_data.magic = AO2_MAGIC; 00263 obj->priv_data.data_size = data_size; 00264 obj->priv_data.ref_counter = 1; 00265 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00266 00267 #ifdef AO2_DEBUG 00268 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00269 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00270 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00271 #endif 00272 00273 /* return a pointer to the user data */ 00274 return EXTERNAL_OBJ(obj); 00275 }
void ao2_bt | ( | void | ) |
Definition at line 82 of file astobj2.c.
References ast_verbose(), free, and N1.
00083 { 00084 int c, i; 00085 #define N1 20 00086 void *addresses[N1]; 00087 char **strings; 00088 00089 c = backtrace(addresses, N1); 00090 strings = backtrace_symbols(addresses,c); 00091 ast_verbose("backtrace returned: %d\n", c); 00092 for(i = 0; i < c; i++) { 00093 ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]); 00094 } 00095 free(strings); 00096 }
void* ao2_callback | ( | struct ao2_container * | c, | |
const enum search_flags | flags, | |||
ao2_callback_fn * | cb_fn, | |||
void * | arg | |||
) |
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Browse the container using different stategies accoding the flags.
Definition at line 447 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(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_list::entry, EXTERNAL_OBJ, free, ao2_container::hash_fn, INTERNAL_OBJ(), last, LOG_WARNING, match(), ao2_container::n_buckets, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, and ao2_container::version.
Referenced by ao2_find(), ao2_unlink(), ast_moh_destroy(), container_destruct(), delete_users(), get_mohbydigit(), load_config(), load_module(), load_moh_classes(), and unload_module().
00450 { 00451 int i, last; /* search boundaries */ 00452 void *ret = NULL; 00453 00454 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00455 return NULL; 00456 00457 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00458 ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); 00459 return NULL; 00460 } 00461 00462 /* override the match function if necessary */ 00463 if (cb_fn == NULL) /* if NULL, match everything */ 00464 cb_fn = cb_true; 00465 /* 00466 * XXX this can be optimized. 00467 * If we have a hash function and lookup by pointer, 00468 * run the hash function. Otherwise, scan the whole container 00469 * (this only for the time being. We need to optimize this.) 00470 */ 00471 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00472 i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00473 else /* don't know, let's scan all buckets */ 00474 i = -1; /* XXX this must be fixed later. */ 00475 00476 /* determine the search boundaries: i..last-1 */ 00477 if (i < 0) { 00478 i = 0; 00479 last = c->n_buckets; 00480 } else { 00481 last = i + 1; 00482 } 00483 00484 ao2_lock(c); /* avoid modifications to the content */ 00485 00486 for (; i < last ; i++) { 00487 /* scan the list with prev-cur pointers */ 00488 struct bucket_list *cur; 00489 00490 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00491 int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP); 00492 00493 /* we found the object, performing operations according flags */ 00494 if (match == 0) { /* no match, no stop, continue */ 00495 continue; 00496 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00497 i = last; 00498 break; 00499 } 00500 /* we have a match (CMP_MATCH) here */ 00501 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00502 /* it is important to handle this case before the unlink */ 00503 ret = EXTERNAL_OBJ(cur->astobj); 00504 ao2_ref(ret, 1); 00505 } 00506 00507 if (flags & OBJ_UNLINK) { /* must unlink */ 00508 struct bucket_list *x = cur; 00509 00510 /* we are going to modify the container, so update version */ 00511 ast_atomic_fetchadd_int(&c->version, 1); 00512 AST_LIST_REMOVE_CURRENT(entry); 00513 /* update number of elements and version */ 00514 ast_atomic_fetchadd_int(&c->elements, -1); 00515 ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00516 free(x); /* free the link record */ 00517 } 00518 00519 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00520 /* We found the only match we need */ 00521 i = last; /* force exit from outer loop */ 00522 break; 00523 } 00524 if (!(flags & OBJ_NODATA)) { 00525 #if 0 /* XXX to be completed */ 00526 /* 00527 * This is the multiple-return case. We need to link 00528 * the object in a list. The refcount is already increased. 00529 */ 00530 #endif 00531 } 00532 } 00533 AST_LIST_TRAVERSE_SAFE_END; 00534 } 00535 ao2_unlock(c); 00536 return ret; 00537 }
struct ao2_container* ao2_container_alloc | ( | const unsigned int | n_buckets, | |
ao2_hash_fn * | hash_fn, | |||
ao2_callback_fn * | cmp_fn | |||
) |
Allocate and initialize a container with the desired number of buckets.
We allocate space for a struct astobj_container, struct container and the buckets[] array.
n_buckets | Number of buckets for hash | |
hash_fn | Pointer to a function computing a hash value. | |
cmp_fn | Pointer to a function comparating key-value with a string. (can be NULL) |
Definition at line 335 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 config_text_file_save(), dialgroup_write(), init_queue(), load_module(), and xml_translate().
00337 { 00338 /* XXX maybe consistency check on arguments ? */ 00339 /* compute the container size */ 00340 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00341 00342 struct ao2_container *c = ao2_alloc(container_size, container_destruct); 00343 00344 if (!c) 00345 return NULL; 00346 00347 c->version = 1; /* 0 is a reserved value here */ 00348 c->n_buckets = n_buckets; 00349 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00350 c->cmp_fn = cmp_fn; 00351 00352 #ifdef AO2_DEBUG 00353 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00354 #endif 00355 00356 return c; 00357 }
int ao2_container_count | ( | struct ao2_container * | c | ) |
Returns the number of elements in a container.
return the number of elements in the container
Definition at line 362 of file astobj2.c.
References ao2_container::elements.
Referenced by __queues_show().
00363 { 00364 return c->elements; 00365 }
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 542 of file astobj2.c.
References ao2_callback(), and ao2_container::cmp_fn.
Referenced by __find_callno(), authenticate_request(), authenticate_verify(), build_peer(), build_user(), compare_weight(), dialgroup_read(), dialgroup_write(), find_peer(), find_profile(), find_pvt(), find_queue_by_name_rt(), find_user(), get_member_penalty(), get_mohbyname(), handle_cli_iax2_unregister(), iax2_destroy_helper(), load_realtime_queue(), phoneprov_callback(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), reload_queue_members(), reload_queues(), remove_from_queue(), rt_handle_member_record(), set_fn(), update_queue(), and xml_translate().
00543 { 00544 return ao2_callback(c, flags, c->cmp_fn, arg); 00545 }
struct ao2_iterator ao2_iterator_init | ( | struct ao2_container * | c, | |
int | flags | |||
) |
initialize an iterator so we start from the first object
Definition at line 550 of file astobj2.c.
References ao2_iterator::c, and ao2_iterator::flags.
Referenced by __iax2_show_peers(), __queues_show(), authenticate_reply(), check_access(), cli_console_active(), cli_list_devices(), compare_weight(), complete_iax2_show_peer(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), delete_profiles(), delete_routes(), destroy_pvts(), dialgroup_read(), dump_queue_members(), free_members(), get_member_status(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_show_routes(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), interface_exists_global(), manager_iax2_show_peer_list(), manager_queues_status(), manager_queues_summary(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload_queues(), set_member_paused(), set_member_penalty(), stop_streams(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and update_status().
00551 { 00552 struct ao2_iterator a = { 00553 .c = c, 00554 .flags = flags 00555 }; 00556 00557 return a; 00558 }
void* ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 563 of file astobj2.c.
References ao2_lock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, F_AO2I_DONTLOCK, 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(), authenticate_reply(), check_access(), cli_console_active(), cli_list_devices(), compare_weight(), complete_iax2_show_peer(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), delete_profiles(), delete_routes(), destroy_pvts(), dialgroup_read(), dump_queue_members(), free_members(), get_member_status(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_show_routes(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), interface_exists_global(), manager_iax2_show_peer_list(), manager_queues_status(), manager_queues_summary(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload_queues(), set_member_paused(), set_member_penalty(), stop_streams(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and update_status().
00564 { 00565 int lim; 00566 struct bucket_list *p = NULL; 00567 void *ret = NULL; 00568 00569 if (INTERNAL_OBJ(a->c) == NULL) 00570 return NULL; 00571 00572 if (!(a->flags & F_AO2I_DONTLOCK)) 00573 ao2_lock(a->c); 00574 00575 /* optimization. If the container is unchanged and 00576 * we have a pointer, try follow it 00577 */ 00578 if (a->c->version == a->c_version && (p = a->obj) ) { 00579 if ( (p = AST_LIST_NEXT(p, entry)) ) 00580 goto found; 00581 /* nope, start from the next bucket */ 00582 a->bucket++; 00583 a->version = 0; 00584 a->obj = NULL; 00585 } 00586 00587 lim = a->c->n_buckets; 00588 00589 /* Browse the buckets array, moving to the next 00590 * buckets if we don't find the entry in the current one. 00591 * Stop when we find an element with version number greater 00592 * than the current one (we reset the version to 0 when we 00593 * switch buckets). 00594 */ 00595 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00596 /* scan the current bucket */ 00597 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00598 if (p->version > a->version) 00599 goto found; 00600 } 00601 } 00602 00603 found: 00604 if (p) { 00605 a->version = p->version; 00606 a->obj = p; 00607 a->c_version = a->c->version; 00608 ret = EXTERNAL_OBJ(p->astobj); 00609 /* inc refcount of returned object */ 00610 ao2_ref(ret, 1); 00611 } 00612 00613 if (!(a->flags & F_AO2I_DONTLOCK)) 00614 ao2_unlock(a->c); 00615 00616 return ret; 00617 }
void* ao2_link | ( | struct ao2_container * | c, | |
void * | newobj | |||
) |
Add an object to a container.
c | the container to operate on. | |
newobj | the object to be added. |
NULL | on errors | |
newobj | on success. |
This function automatically increases the reference count to account for the reference that the container now holds to the object.
Definition at line 381 of file astobj2.c.
References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_list::entry, INTERNAL_OBJ(), and OBJ_POINTER.
Referenced by add_to_queue(), build_device(), build_route(), dialgroup_write(), moh_register(), reload_queues(), rt_handle_member_record(), set_config(), set_fn(), store_by_peercallno(), store_by_transfercallno(), and xml_translate().
00382 { 00383 int i; 00384 /* create a new list entry */ 00385 struct bucket_list *p; 00386 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00387 00388 if (!obj) 00389 return NULL; 00390 00391 if (INTERNAL_OBJ(c) == NULL) 00392 return NULL; 00393 00394 p = ast_calloc(1, sizeof(*p)); 00395 if (!p) 00396 return NULL; 00397 00398 i = c->hash_fn(user_data, OBJ_POINTER); 00399 00400 ao2_lock(c); 00401 i %= c->n_buckets; 00402 p->astobj = obj; 00403 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00404 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00405 ast_atomic_fetchadd_int(&c->elements, 1); 00406 ao2_ref(user_data, +1); 00407 ao2_unlock(c); 00408 00409 return p; 00410 }
int ao2_lock | ( | void * | a | ) |
Lock an object.
a | A pointer to the object we want lock. |
Definition at line 130 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_lock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __queues_show(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), ring_entry(), set_member_paused(), set_member_penalty(), try_calling(), update_queue(), update_realtime_members(), and update_status().
00134 { 00135 struct astobj2 *p = INTERNAL_OBJ(user_data); 00136 00137 if (p == NULL) 00138 return -1; 00139 00140 #ifdef AO2_DEBUG 00141 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00142 #endif 00143 00144 #ifndef DEBUG_THREADS 00145 return ast_mutex_lock(&p->priv_data.lock); 00146 #else 00147 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00148 #endif 00149 }
int ao2_match_by_addr | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) |
int ao2_ref | ( | void * | o, | |
int | delta | |||
) |
Reference/unreference an object and return the old refcount.
o | A pointer to the object | |
delta | Value to add to the reference counter. |
If the refcount goes to zero, the object is destroyed.
if we know the pointer to an object, it is because we have a reference count to it, so the only case when the object can go away is when we release our reference, and it is the last one in existence.
Definition at line 200 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 __find_callno(), __queues_show(), __unload_module(), add_to_queue(), alloc_queue(), announce_thread(), ao2_callback(), ao2_link(), ast_closestream(), ast_filestream_frame_freed(), ast_make_file_from_fd(), ast_readaudio_callback(), ast_readframe(), ast_readvideo_callback(), ast_tcptls_client_start(), ast_tcptls_server_root(), cd_cb(), compare_weight(), complete_queue_remove_member(), conf_free(), conf_run(), config_text_file_save(), copy_socket_data(), destroy_queue(), dialgroup_read(), dialgroup_write(), dump_queue_members(), end_bridge_callback(), end_bridge_callback_data_fixup(), free_members(), get_member_penalty(), get_member_status(), group_destroy(), hangupcalls(), httpd_helper_thread(), iax2_destroy(), interface_exists(), interface_exists_global(), load_module(), manager_queues_status(), manager_queues_summary(), new_iax(), num_available_members(), parse_moved_contact(), peer_ref(), peer_unref(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_ref(), queue_unref(), ref_pvt(), reload_queues(), remove_from_queue(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), set_socket_transport(), sip_destroy_peer(), sip_prepare_socket(), sip_tcp_locate(), try_calling(), unload_module(), unref_profile(), unref_pvt(), unref_route(), update_queue(), update_realtime_members(), update_status(), user_ref(), user_unref(), and xml_translate().
00201 { 00202 int current_value; 00203 int ret; 00204 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00205 00206 if (obj == NULL) 00207 return -1; 00208 00209 /* if delta is 0, just return the refcount */ 00210 if (delta == 0) 00211 return (obj->priv_data.ref_counter); 00212 00213 /* we modify with an atomic operation the reference counter */ 00214 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00215 current_value = ret + delta; 00216 00217 #ifdef AO2_DEBUG 00218 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00219 #endif 00220 00221 /* this case must never happen */ 00222 if (current_value < 0) 00223 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00224 00225 if (current_value <= 0) { /* last reference, destroy the object */ 00226 if (obj->priv_data.destructor_fn != NULL) 00227 obj->priv_data.destructor_fn(user_data); 00228 00229 ast_mutex_destroy(&obj->priv_data.lock); 00230 #ifdef AO2_DEBUG 00231 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00232 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00233 #endif 00234 /* for safety, zero-out the astobj2 header and also the 00235 * first word of the user-data, which we make sure is always 00236 * allocated. */ 00237 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00238 free(obj); 00239 } 00240 00241 return ret; 00242 }
int ao2_trylock | ( | void * | a | ) |
Try locking-- (don't block if fail).
a | A pointer to the object we want to lock. |
Definition at line 174 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00178 { 00179 struct astobj2 *p = INTERNAL_OBJ(user_data); 00180 int ret; 00181 00182 if (p == NULL) 00183 return -1; 00184 #ifndef DEBUG_THREADS 00185 ret = ast_mutex_trylock(&p->priv_data.lock); 00186 #else 00187 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00188 #endif 00189 00190 #ifdef AO2_DEBUG 00191 if (!ret) 00192 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00193 #endif 00194 return ret; 00195 }
void* ao2_unlink | ( | struct ao2_container * | c, | |
void * | obj | |||
) |
Remove an object from the container.
NULL,always |
If the object gets unlinked from the container, the container's reference to the object will be automatically released.
Definition at line 424 of file astobj2.c.
References ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
Referenced by build_user(), delete_profiles(), delete_routes(), destroy_pvts(), dialgroup_write(), find_queue_by_name_rt(), free_members(), handle_cli_iax2_prune_realtime(), leave_queue(), prune_users(), reload_queues(), remove_by_peercallno(), remove_by_transfercallno(), remove_from_queue(), unlink_peer(), unload_module(), and update_realtime_members().
00425 { 00426 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00427 return NULL; 00428 00429 ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00430 00431 return NULL; 00432 }
int ao2_unlock | ( | void * | a | ) |
Unlock an object.
a | A pointer to the object we want unlock. |
Definition at line 152 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_unlock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __queues_show(), add_to_queue(), ao2_callback(), ao2_link(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), ring_entry(), set_member_paused(), set_member_penalty(), try_calling(), update_queue(), update_realtime_members(), and update_status().
00156 { 00157 struct astobj2 *p = INTERNAL_OBJ(user_data); 00158 00159 if (p == NULL) 00160 return -1; 00161 00162 #ifdef AO2_DEBUG 00163 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00164 #endif 00165 00166 #ifndef DEBUG_THREADS 00167 return ast_mutex_unlock(&p->priv_data.lock); 00168 #else 00169 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00170 #endif 00171 }
int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 774 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
00775 { 00776 #ifdef AO2_DEBUG 00777 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 00778 #endif 00779 00780 return 0; 00781 }
static int cb_true | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
special callback that matches all
Definition at line 437 of file astobj2.c.
References CMP_MATCH.
Referenced by ao2_callback().
00438 { 00439 return CMP_MATCH; 00440 }
static int cd_cb | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 622 of file astobj2.c.
References ao2_ref().
Referenced by container_destruct().
00623 { 00624 ao2_ref(obj, -1); 00625 return 0; 00626 }
static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 628 of file astobj2.c.
References ao2_callback(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_list::entry, ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by ao2_container_alloc().
00629 { 00630 struct ao2_container *c = _c; 00631 int i; 00632 00633 ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00634 00635 for (i = 0; i < c->n_buckets; i++) { 00636 struct bucket_list *cur; 00637 00638 while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00639 ast_free(cur); 00640 } 00641 } 00642 00643 #ifdef AO2_DEBUG 00644 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00645 #endif 00646 }
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 326 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 104 of file astobj2.c.
References AO2_MAGIC, ast_log(), and LOG_ERROR.
Referenced by ao2_callback(), ao2_iterator_next(), ao2_link(), ao2_lock(), ao2_ref(), ao2_trylock(), ao2_unlink(), and ao2_unlock().
00105 { 00106 struct astobj2 *p; 00107 00108 if (!user_data) { 00109 ast_log(LOG_ERROR, "user_data is NULL\n"); 00110 return NULL; 00111 } 00112 00113 p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); 00114 if (AO2_MAGIC != (p->priv_data.magic) ) { 00115 ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p); 00116 p = NULL; 00117 } 00118 00119 return p; 00120 }