#include "asterisk.h"#include "asterisk/_private.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_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. | |
| 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. | |
| 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) |
| void | ao2_iterator_destroy (struct ao2_iterator *i) |
| Destroy a container iterator. | |
| struct 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) |
| 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(), ao2_callback(), and ao2_iterator_next().
| 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(), __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, __priv_data::lock, __priv_data::magic, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by add_calltoken_ignore(), alloc_queue(), ao2_container_alloc(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_callno_limits(), build_device(), build_peer(), build_profile(), build_route(), build_user(), conf_run(), create_callno_pools(), create_queue_member(), dialgroup_write(), get_filestream(), get_lock(), moh_class_malloc(), new_iax(), peercnt_add(), set_fn(), sip_alloc(), try_calling(), 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_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_CONTINUE, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, and ao2_container::version.
Referenced by ao2_find(), ao2_unlink(), ast_moh_destroy(), calltoken_required(), container_destruct(), delete_users(), get_mohbydigit(), load_config(), load_module(), load_moh_classes(), reload_config(), set_config_destroy(), set_peercnt_limit(), and unload_module().
00450 { 00451 int i, start, 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 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00473 else /* don't know, let's scan all buckets */ 00474 start = i = -1; /* XXX this must be fixed later. */ 00475 00476 /* determine the search boundaries: i..last-1 */ 00477 if (i < 0) { 00478 start = i = 0; 00479 last = c->n_buckets; 00480 } else if ((flags & OBJ_CONTINUE)) { 00481 last = c->n_buckets; 00482 } else { 00483 last = i + 1; 00484 } 00485 00486 ao2_lock(c); /* avoid modifications to the content */ 00487 00488 for (; i < last ; i++) { 00489 /* scan the list with prev-cur pointers */ 00490 struct bucket_list *cur; 00491 00492 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00493 int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP); 00494 00495 /* we found the object, performing operations according flags */ 00496 if (match == 0) { /* no match, no stop, continue */ 00497 continue; 00498 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00499 i = last; 00500 break; 00501 } 00502 /* we have a match (CMP_MATCH) here */ 00503 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00504 /* it is important to handle this case before the unlink */ 00505 ret = EXTERNAL_OBJ(cur->astobj); 00506 ao2_ref(ret, 1); 00507 } 00508 00509 if (flags & OBJ_UNLINK) { /* must unlink */ 00510 struct bucket_list *x = cur; 00511 00512 /* we are going to modify the container, so update version */ 00513 ast_atomic_fetchadd_int(&c->version, 1); 00514 AST_LIST_REMOVE_CURRENT(entry); 00515 /* update number of elements and version */ 00516 ast_atomic_fetchadd_int(&c->elements, -1); 00517 ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00518 free(x); /* free the link record */ 00519 } 00520 00521 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00522 /* We found the only match we need */ 00523 i = last; /* force exit from outer loop */ 00524 break; 00525 } 00526 if (!(flags & OBJ_NODATA)) { 00527 #if 0 /* XXX to be completed */ 00528 /* 00529 * This is the multiple-return case. We need to link 00530 * the object in a list. The refcount is already increased. 00531 */ 00532 #endif 00533 } 00534 } 00535 AST_LIST_TRAVERSE_SAFE_END; 00536 00537 if (ret) { 00538 /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ 00539 break; 00540 } 00541 00542 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00543 /* Move to the beginning to ensure we check every bucket */ 00544 i = -1; 00545 last = start; 00546 } 00547 } 00548 ao2_unlock(c); 00549 return ret; 00550 }
| struct ao2_container* ao2_container_alloc | ( | const unsigned int | n_buckets, | |
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [read] |
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(), create_callno_pools(), dialgroup_write(), get_lock(), init_queue(), load_module(), load_objects(), 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(), get_unused_callno(), lock_broker(), and unload_module().
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 555 of file astobj2.c.
References ao2_callback(), and ao2_container::cmp_fn.
Referenced by __find_callno(), add_calltoken_ignore(), authenticate_request(), authenticate_verify(), build_callno_limits(), 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(), get_unused_callno(), handle_cli_iax2_unregister(), iax2_destroy_helper(), load_realtime_queue(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), phoneprov_callback(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), reload_queue_members(), reload_queues(), remove_from_queue(), rt_handle_member_record(), sched_delay_remove(), set_fn(), update_queue(), and xml_translate().
00556 { 00557 return ao2_callback(c, flags, c->cmp_fn, arg); 00558 }
| void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 578 of file astobj2.c.
References ao2_ref(), and ao2_iterator::c.
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(), find_queue_by_name_rt(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), 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(), set_member_paused(), set_member_penalty(), stop_streams(), try_calling(), unload_module(), update_queue(), and update_realtime_members().
| struct ao2_iterator ao2_iterator_init | ( | struct ao2_container * | c, | |
| int | flags | |||
| ) | [read] |
Create an iterator for a container.
initialize an iterator so we start from the first object
Definition at line 563 of file astobj2.c.
References ao2_ref(), 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(), find_queue_by_name_rt(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), 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 struct ao2_iterator a = { 00566 .c = c, 00567 .flags = flags 00568 }; 00569 00570 ao2_ref(c, +1); 00571 00572 return a; 00573 }
| void* ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 587 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, ao2_lock(), ao2_ref(), ao2_unlock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, bucket_list::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, bucket_list::version, ao2_iterator::version, and ao2_container::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(), find_queue_by_name_rt(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), 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().
00588 { 00589 int lim; 00590 struct bucket_list *p = NULL; 00591 void *ret = NULL; 00592 00593 if (INTERNAL_OBJ(a->c) == NULL) 00594 return NULL; 00595 00596 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00597 ao2_lock(a->c); 00598 00599 /* optimization. If the container is unchanged and 00600 * we have a pointer, try follow it 00601 */ 00602 if (a->c->version == a->c_version && (p = a->obj) ) { 00603 if ( (p = AST_LIST_NEXT(p, entry)) ) 00604 goto found; 00605 /* nope, start from the next bucket */ 00606 a->bucket++; 00607 a->version = 0; 00608 a->obj = NULL; 00609 } 00610 00611 lim = a->c->n_buckets; 00612 00613 /* Browse the buckets array, moving to the next 00614 * buckets if we don't find the entry in the current one. 00615 * Stop when we find an element with version number greater 00616 * than the current one (we reset the version to 0 when we 00617 * switch buckets). 00618 */ 00619 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00620 /* scan the current bucket */ 00621 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00622 if (p->version > a->version) 00623 goto found; 00624 } 00625 } 00626 00627 found: 00628 if (p) { 00629 a->version = p->version; 00630 a->obj = p; 00631 a->c_version = a->c->version; 00632 ret = EXTERNAL_OBJ(p->astobj); 00633 /* inc refcount of returned object */ 00634 ao2_ref(ret, 1); 00635 } 00636 00637 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00638 ao2_unlock(a->c); 00639 00640 return ret; 00641 }
| 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::astobj, INTERNAL_OBJ(), OBJ_POINTER, and bucket_list::version.
Referenced by add_calltoken_ignore(), add_to_queue(), build_callno_limits(), build_device(), build_profile(), build_route(), create_callno_pools(), dialgroup_write(), find_queue_by_name_rt(), get_lock(), moh_register(), peercnt_add(), realtime_peer(), realtime_user(), reload_queues(), replace_callno(), 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 = abs(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_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), 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(), replace_callno(), 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(), __sip_destroy(), __unload_module(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), alloc_queue(), announce_thread(), ao2_callback(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_link(), ast_closestream(), ast_make_file_from_fd(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_callno_limits(), calltoken_required(), cd_cb(), compare_weight(), complete_queue_remove_member(), conf_free(), conf_run(), config_text_file_save(), copy_socket_data(), create_callno_pools(), destroy_queue(), dialgroup_read(), dialgroup_write(), dialog_ref(), dialog_unref(), dump_queue_members(), end_bridge_callback(), end_bridge_callback_data_fixup(), find_queue_by_name_rt(), free_members(), get_lock(), get_member_penalty(), get_member_status(), group_destroy(), handle_cli_iax2_show_callno_limits(), hangupcalls(), httpd_helper_thread(), iax2_destroy(), interface_exists(), interface_exists_global(), load_module(), load_objects(), manager_queues_status(), manager_queues_summary(), new_iax(), num_available_members(), parse_moved_contact(), peer_ref(), peer_unref(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), peercnt_remove_cb(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_ref(), queue_unref(), ref_pvt(), reload_queues(), remove_from_queue(), replace_callno(), rt_handle_member_record(), sched_delay_remove(), session_do(), set_member_paused(), set_member_penalty(), set_peercnt_limit(), 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(), get_lock(), handle_cli_iax2_prune_realtime(), leave_queue(), peercnt_remove(), 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_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), 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(), replace_callno(), 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 798 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
00799 { 00800 #ifdef AO2_DEBUG 00801 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 00802 #endif 00803 00804 return 0; 00805 }
| 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 646 of file astobj2.c.
References ao2_ref().
Referenced by container_destruct().
00647 { 00648 ao2_ref(obj, -1); 00649 return 0; 00650 }
| static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 652 of file astobj2.c.
References ao2_callback(), ast_atomic_fetchadd_int(), 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().
00653 { 00654 struct ao2_container *c = _c; 00655 int i; 00656 00657 ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00658 00659 for (i = 0; i < c->n_buckets; i++) { 00660 struct bucket_list *cur; 00661 00662 while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00663 ast_free(cur); 00664 } 00665 } 00666 00667 #ifdef AO2_DEBUG 00668 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00669 #endif 00670 }
| 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 | ) | [static, read] |
convert from a pointer _p to a user-defined object
Definition at line 104 of file astobj2.c.
References AO2_MAGIC, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.
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 }
1.5.6