#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_entry |
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 | REF_FILE "/tmp/refs" |
Enumerations | |
| enum | ao2_callback_type { DEFAULT, WITH_DATA } |
Functions | |
| void * | __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn) |
| void * | __ao2_alloc_debug (size_t data_size, ao2_destructor_fn destructor_fn, const char *tag, const char *file, int line, const char *funcname, int ref_debug) |
| void * | __ao2_callback (struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg) |
| void * | __ao2_callback_data (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data) |
| void * | __ao2_callback_data_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, char *file, int line, const char *funcname) |
| void * | __ao2_callback_debug (struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, const char *tag, char *file, int line, const char *funcname) |
| struct ao2_container * | __ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| struct ao2_container * | __ao2_container_alloc_debug (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, const char *tag, char *file, int line, const char *funcname, int ref_debug) |
| void * | __ao2_find (struct ao2_container *c, const void *arg, enum search_flags flags) |
| void * | __ao2_find_debug (struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, char *file, int line, const char *funcname) |
| void * | __ao2_iterator_next (struct ao2_iterator *a) |
| void * | __ao2_iterator_next_debug (struct ao2_iterator *a, const char *tag, char *file, int line, const char *funcname) |
| void * | __ao2_link (struct ao2_container *c, void *user_data, int flags) |
| void * | __ao2_link_debug (struct ao2_container *c, void *user_data, int flags, const char *tag, char *file, int line, const char *funcname) |
| int | __ao2_lock (void *user_data, const char *file, const char *func, int line, const char *var) |
| Lock an object. | |
| int | __ao2_ref (void *user_data, const int delta) |
| int | __ao2_ref_debug (void *user_data, const int delta, const char *tag, char *file, int line, const char *funcname) |
| int | __ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var) |
| Try locking-- (don't block if fail). | |
| void * | __ao2_unlink (struct ao2_container *c, void *user_data, int flags) |
| void * | __ao2_unlink_debug (struct ao2_container *c, void *user_data, int flags, const char *tag, char *file, int line, const char *funcname) |
| int | __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var) |
| Unlock an object. | |
| void | ao2_bt (void) |
| int | ao2_container_count (struct ao2_container *c) |
| Returns the number of elements in a container. | |
| 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. | |
| int | ao2_match_by_addr (void *user_data, void *arg, int flags) |
| another convenience function is a callback that matches on address | |
| void * | ao2_object_get_lockaddr (void *obj) |
| Return the lock address of an object. | |
| int | astobj2_init (void) |
| static int | cb_true (void *user_data, void *arg, int flags) |
| special callback that matches all | |
| static int | cb_true_data (void *user_data, void *arg, void *data, int flags) |
| similar to cb_true, but is an ao2_callback_data_fn instead | |
| static int | cd_cb (void *obj, void *arg, int flag) |
| static int | cd_cb_debug (void *obj, void *arg, int flag) |
| static void | container_destruct (void *c) |
| static void | container_destruct_debug (void *c) |
| static int | hash_zero (const void *user_obj, const int flags) |
| always zero hash function | |
| static void * | internal_ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname) |
| static void * | internal_ao2_callback (struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag, char *file, int line, const char *funcname) |
| static struct ao2_container * | internal_ao2_container_alloc (struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| static struct ao2_container * | internal_ao2_container_alloc (struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| static void * | internal_ao2_iterator_next (struct ao2_iterator *a, struct bucket_entry **q) |
| static struct bucket_entry * | internal_ao2_link (struct ao2_container *c, void *user_data, int flags, const char *file, int line, const char *func) |
| static int | internal_ao2_ref (void *user_data, const int delta) |
| 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 133 of file astobj2.c.
Referenced by internal_ao2_alloc(), internal_ao2_callback(), and internal_ao2_iterator_next().
| #define REF_FILE "/tmp/refs" |
| enum ao2_callback_type |
| void* __ao2_alloc | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn | |||
| ) |
Definition at line 342 of file astobj2.c.
References internal_ao2_alloc().
Referenced by __ao2_container_alloc().
00343 { 00344 return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__); 00345 }
| void* __ao2_alloc_debug | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn, | |||
| const char * | tag, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | funcname, | |||
| int | ref_debug | |||
| ) |
Definition at line 322 of file astobj2.c.
References internal_ao2_alloc(), and REF_FILE.
Referenced by __ao2_container_alloc_debug(), __ast_channel_alloc_ap(), _moh_class_malloc(), and ast_dummy_channel_alloc().
00324 { 00325 /* allocation */ 00326 void *obj; 00327 FILE *refo; 00328 00329 if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) { 00330 return NULL; 00331 } 00332 00333 if (ref_debug && (refo = fopen(REF_FILE, "a"))) { 00334 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag); 00335 fclose(refo); 00336 } 00337 00338 /* return a pointer to the user data */ 00339 return obj; 00340 }
| void* __ao2_callback | ( | struct ao2_container * | c, | |
| enum search_flags | flags, | |||
| ao2_callback_fn * | cb_fn, | |||
| void * | arg | |||
| ) |
Definition at line 784 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find(), __ao2_unlink(), and container_destruct().
00786 { 00787 return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL); 00788 }
| void* __ao2_callback_data | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_data_fn * | cb_fn, | |||
| void * | arg, | |||
| void * | data | |||
| ) |
Definition at line 798 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
00800 { 00801 return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL); 00802 }
| void* __ao2_callback_data_debug | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_data_fn * | cb_fn, | |||
| void * | arg, | |||
| void * | data, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 790 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
00794 { 00795 return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname); 00796 }
| void* __ao2_callback_debug | ( | struct ao2_container * | c, | |
| enum search_flags | flags, | |||
| ao2_callback_fn * | cb_fn, | |||
| void * | arg, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 777 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find_debug(), __ao2_unlink_debug(), and container_destruct_debug().
00780 { 00781 return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname); 00782 }
| struct ao2_container* __ao2_container_alloc | ( | const unsigned int | n_buckets, | |
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [read] |
Definition at line 442 of file astobj2.c.
References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().
Referenced by internal_ao2_callback().
00444 { 00445 /* XXX maybe consistency check on arguments ? */ 00446 /* compute the container size */ 00447 00448 const unsigned int num_buckets = hash_fn ? n_buckets : 1; 00449 size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket); 00450 struct ao2_container *c = __ao2_alloc(container_size, container_destruct); 00451 00452 return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn); 00453 }
| struct ao2_container* __ao2_container_alloc_debug | ( | const unsigned int | n_buckets, | |
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname, | |||
| int | ref_debug | |||
| ) | [read] |
Definition at line 429 of file astobj2.c.
References __ao2_alloc_debug(), container_destruct_debug(), and internal_ao2_container_alloc().
00432 { 00433 /* XXX maybe consistency check on arguments ? */ 00434 /* compute the container size */ 00435 const unsigned int num_buckets = hash_fn ? n_buckets : 1; 00436 size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket); 00437 struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug); 00438 00439 return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn); 00440 }
| void* __ao2_find | ( | struct ao2_container * | c, | |
| const void * | arg, | |||
| enum search_flags | flags | |||
| ) |
Definition at line 814 of file astobj2.c.
References __ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00815 { 00816 void *arged = (void *) arg;/* Done to avoid compiler const warning */ 00817 00818 return __ao2_callback(c, flags, c->cmp_fn, arged); 00819 }
| void* __ao2_find_debug | ( | struct ao2_container * | c, | |
| const void * | arg, | |||
| enum search_flags | flags, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
the find function just invokes the default callback with some reasonable flags.
Definition at line 807 of file astobj2.c.
References __ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00808 { 00809 void *arged = (void *) arg;/* Done to avoid compiler const warning */ 00810 00811 return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, funcname); 00812 }
| void* __ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 937 of file astobj2.c.
References __ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().
00938 { 00939 struct bucket_entry *p = NULL; 00940 void *ret = NULL; 00941 00942 ret = internal_ao2_iterator_next(a, &p); 00943 00944 if (p) { 00945 /* inc refcount of returned object */ 00946 __ao2_ref(ret, 1); 00947 } 00948 00949 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00950 ao2_unlock(a->c); 00951 00952 return ret; 00953 }
| void* __ao2_iterator_next_debug | ( | struct ao2_iterator * | a, | |
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 919 of file astobj2.c.
References __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().
00920 { 00921 struct bucket_entry *p; 00922 void *ret = NULL; 00923 00924 ret = internal_ao2_iterator_next(a, &p); 00925 00926 if (p) { 00927 /* inc refcount of returned object */ 00928 __ao2_ref_debug(ret, 1, tag, file, line, funcname); 00929 } 00930 00931 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00932 ao2_unlock(a->c); 00933 00934 return ret; 00935 }
| void* __ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| int | flags | |||
| ) |
Definition at line 523 of file astobj2.c.
References __ao2_ref(), ao2_unlock, internal_ao2_link(), and OBJ_NOLOCK.
Referenced by internal_ao2_callback().
00524 { 00525 struct bucket_entry *p = internal_ao2_link(c, user_data, flags, __FILE__, __LINE__, __PRETTY_FUNCTION__); 00526 00527 if (p) { 00528 __ao2_ref(user_data, +1); 00529 if (!(flags & OBJ_NOLOCK)) { 00530 ao2_unlock(c); 00531 } 00532 } 00533 return p; 00534 }
| void* __ao2_link_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| int | flags, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 510 of file astobj2.c.
References __ao2_ref_debug(), ao2_unlock, internal_ao2_link(), and OBJ_NOLOCK.
Referenced by internal_ao2_callback().
00511 { 00512 struct bucket_entry *p = internal_ao2_link(c, user_data, flags, file, line, funcname); 00513 00514 if (p) { 00515 __ao2_ref_debug(user_data, +1, tag, file, line, funcname); 00516 if (!(flags & OBJ_NOLOCK)) { 00517 ao2_unlock(c); 00518 } 00519 } 00520 return p; 00521 }
| int __ao2_lock | ( | void * | a, | |
| const char * | file, | |||
| const char * | func, | |||
| int | line, | |||
| const char * | var | |||
| ) |
Lock an object.
| a | A pointer to the object we want to lock. |
Definition at line 146 of file astobj2.c.
References __ast_pthread_mutex_lock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00147 { 00148 struct astobj2 *p = INTERNAL_OBJ(user_data); 00149 00150 if (p == NULL) 00151 return -1; 00152 00153 #ifdef AO2_DEBUG 00154 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00155 #endif 00156 00157 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00158 }
| int __ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) |
Definition at line 230 of file astobj2.c.
References internal_ao2_ref(), and INTERNAL_OBJ().
Referenced by __ao2_iterator_next(), __ao2_link(), cd_cb(), and internal_ao2_callback().
00231 { 00232 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00233 00234 if (obj == NULL) 00235 return -1; 00236 00237 return internal_ao2_ref(user_data, delta); 00238 }
| int __ao2_ref_debug | ( | void * | user_data, | |
| const int | delta, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 205 of file astobj2.c.
References __priv_data::destructor_fn, internal_ao2_ref(), INTERNAL_OBJ(), astobj2::priv_data, __priv_data::ref_counter, and REF_FILE.
Referenced by __ao2_iterator_next_debug(), __ao2_link_debug(), cd_cb_debug(), dialog_ref_debug(), dialog_unref_debug(), and internal_ao2_callback().
00206 { 00207 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00208 00209 if (obj == NULL) 00210 return -1; 00211 00212 if (delta != 0) { 00213 FILE *refo = fopen(REF_FILE, "a"); 00214 if (refo) { 00215 fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"), 00216 delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1); 00217 fclose(refo); 00218 } 00219 } 00220 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */ 00221 FILE *refo = fopen(REF_FILE, "a"); 00222 if (refo) { 00223 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag); 00224 fclose(refo); 00225 } 00226 } 00227 return internal_ao2_ref(user_data, delta); 00228 }
| int __ao2_trylock | ( | void * | a, | |
| const char * | file, | |||
| const char * | func, | |||
| int | line, | |||
| const char * | var | |||
| ) |
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_pthread_mutex_trylock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00175 { 00176 struct astobj2 *p = INTERNAL_OBJ(user_data); 00177 int ret; 00178 00179 if (p == NULL) 00180 return -1; 00181 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00182 00183 #ifdef AO2_DEBUG 00184 if (!ret) 00185 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00186 #endif 00187 return ret; 00188 }
| void* __ao2_unlink | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| int | flags | |||
| ) |
Definition at line 561 of file astobj2.c.
References __ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00562 { 00563 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00564 return NULL; 00565 00566 flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA); 00567 __ao2_callback(c, flags, ao2_match_by_addr, user_data); 00568 00569 return NULL; 00570 }
| void* __ao2_unlink_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| int | flags, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 548 of file astobj2.c.
References __ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00550 { 00551 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00552 return NULL; 00553 00554 flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA); 00555 00556 __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, funcname); 00557 00558 return NULL; 00559 }
| int __ao2_unlock | ( | void * | a, | |
| const char * | file, | |||
| const char * | func, | |||
| int | line, | |||
| const char * | var | |||
| ) |
Unlock an object.
| a | A pointer to the object we want unlock. |
Definition at line 160 of file astobj2.c.
References __ast_pthread_mutex_unlock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00161 { 00162 struct astobj2 *p = INTERNAL_OBJ(user_data); 00163 00164 if (p == NULL) 00165 return -1; 00166 00167 #ifdef AO2_DEBUG 00168 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00169 #endif 00170 00171 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00172 }
| 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 458 of file astobj2.c.
References ao2_container::elements.
Referenced by __ast_data_register(), __ast_manager_event_multichan(), __queues_show(), _sip_show_peers(), action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_lock_unlock_helper(), action_mute_unmute_helper(), ast_active_channels(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_identical(), ast_format_cap_is_empty(), ast_format_cap_joint(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_tone_zone_count(), build_format_list_array(), calc_metric(), cc_cli_output_status(), cleanup(), cli_fax_show_sessions(), cli_tps_report(), data_odbc_provider_handler(), data_provider_release(), data_provider_release_all(), do_timing(), endelm(), func_confbridge_info(), get_unused_callno(), handle_cli_iax2_show_callno_limits(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), joint_copy_helper(), list_hash_cb(), locals_show(), lock_broker(), match_filter(), meetme_data_provider_get(), pthread_timer_open(), queue_exec(), queue_function_mem_read(), queues_data_provider_get_helper(), try_calling(), and unload_module().
00459 { 00460 return c->elements; 00461 }
| void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 839 of file astobj2.c.
References AO2_ITERATOR_MALLOCD, ao2_ref, ast_free, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_confbridgelistrooms(), action_meetmelist(), alias_show(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_has_joint(), ast_format_cap_has_type(), ast_format_cap_identical(), ast_format_cap_iter_end(), ast_format_cap_joint(), ast_format_cap_to_old_bitfield(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_destroy(), ast_srtp_unprotect(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), build_format_list_array(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_confbridge_name(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_meetmecmd(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), conf_queue_dtmf(), conf_run(), data_filter_find(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), extension_state_cb(), fax_session_tab_complete(), find_call(), find_queue_by_name_rt(), find_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_confbridge_list(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_indication_show(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), joint_copy_helper(), kill_duplicate_offers(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().
00840 { 00841 ao2_ref(i->c, -1); 00842 if (i->flags & AO2_ITERATOR_MALLOCD) { 00843 ast_free(i); 00844 } else { 00845 i->c = NULL; 00846 } 00847 }
| 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 824 of file astobj2.c.
References ao2_ref, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_confbridgelistrooms(), action_meetmelist(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_has_joint(), ast_format_cap_has_type(), ast_format_cap_identical(), ast_format_cap_iter_start(), ast_format_cap_joint(), ast_format_cap_to_old_bitfield(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_init(), ast_srtp_unprotect(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), build_format_list_array(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_confbridge_name(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_meetmecmd(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), conf_queue_dtmf(), conf_run(), data_filter_find(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), extension_state_cb(), fax_session_tab_complete(), find_queue_by_name_rt(), find_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_confbridge_list(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_callback(), joint_copy_helper(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().
00825 { 00826 struct ao2_iterator a = { 00827 .c = c, 00828 .flags = flags 00829 }; 00830 00831 ao2_ref(c, +1); 00832 00833 return a; 00834 }
| int ao2_match_by_addr | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) |
| void* ao2_object_get_lockaddr | ( | void * | obj | ) |
Return the lock address of an object.
| [in] | obj | A pointer to the object we want. |
Definition at line 190 of file astobj2.c.
References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), and db_sync_thread().
00191 { 00192 struct astobj2 *p = INTERNAL_OBJ(obj); 00193 00194 if (p == NULL) 00195 return NULL; 00196 00197 return &p->priv_data.lock; 00198 }
| int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1143 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
01144 { 01145 #ifdef AO2_DEBUG 01146 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 01147 #endif 01148 01149 return 0; 01150 }
| static int cb_true | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
special callback that matches all
Definition at line 575 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
00576 { 00577 return CMP_MATCH; 00578 }
| static int cb_true_data | ( | void * | user_data, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
similar to cb_true, but is an ao2_callback_data_fn instead
Definition at line 583 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
00584 { 00585 return CMP_MATCH; 00586 }
| static int cd_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 958 of file astobj2.c.
References __ao2_ref().
Referenced by container_destruct().
00959 { 00960 __ao2_ref(obj, -1); 00961 return 0; 00962 }
| static int cd_cb_debug | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 964 of file astobj2.c.
References __ao2_ref_debug().
Referenced by container_destruct_debug().
00965 { 00966 __ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00967 return 0; 00968 }
| static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 970 of file astobj2.c.
References __ao2_callback(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_entry::entry, ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by __ao2_container_alloc().
00971 { 00972 struct ao2_container *c = _c; 00973 int i; 00974 00975 __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00976 00977 for (i = 0; i < c->n_buckets; i++) { 00978 struct bucket_entry *current; 00979 00980 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00981 ast_free(current); 00982 } 00983 } 00984 00985 #ifdef AO2_DEBUG 00986 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00987 #endif 00988 }
| static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 990 of file astobj2.c.
References __ao2_callback_debug(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb_debug(), bucket_entry::entry, ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by __ao2_container_alloc_debug().
00991 { 00992 struct ao2_container *c = _c; 00993 int i; 00994 00995 __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00996 00997 for (i = 0; i < c->n_buckets; i++) { 00998 struct bucket_entry *current; 00999 01000 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 01001 ast_free(current); 01002 } 01003 } 01004 01005 #ifdef AO2_DEBUG 01006 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 01007 #endif 01008 }
| 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 400 of file astobj2.c.
Referenced by internal_ao2_container_alloc().
| static void* internal_ao2_alloc | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) | [static] |
Definition at line 289 of file astobj2.c.
References __ast_calloc(), 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 __ao2_alloc(), and __ao2_alloc_debug().
00290 { 00291 /* allocation */ 00292 struct astobj2 *obj; 00293 00294 if (data_size < sizeof(void *)) 00295 data_size = sizeof(void *); 00296 00297 #if defined(__AST_DEBUG_MALLOC) 00298 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname); 00299 #else 00300 obj = ast_calloc(1, sizeof(*obj) + data_size); 00301 #endif 00302 00303 if (obj == NULL) 00304 return NULL; 00305 00306 ast_mutex_init(&obj->priv_data.lock); 00307 obj->priv_data.magic = AO2_MAGIC; 00308 obj->priv_data.data_size = data_size; 00309 obj->priv_data.ref_counter = 1; 00310 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00311 00312 #ifdef AO2_DEBUG 00313 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00314 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00315 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00316 #endif 00317 00318 /* return a pointer to the user data */ 00319 return EXTERNAL_OBJ(obj); 00320 }
| static void * internal_ao2_callback | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| void * | cb_fn, | |||
| void * | arg, | |||
| void * | data, | |||
| enum ao2_callback_type | type, | |||
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) | [static] |
Browse the container using different stategies accoding the flags.
Definition at line 596 of file astobj2.c.
References __ao2_container_alloc(), __ao2_link(), __ao2_link_debug(), __ao2_ref(), __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), AO2_ITERATOR_MALLOCD, AO2_ITERATOR_UNLINK, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_calloc, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, bucket_entry::astobj, ao2_container::buckets, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_container::hash_fn, INTERNAL_OBJ(), last, match(), ao2_container::n_buckets, OBJ_CONTINUE, OBJ_KEY, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, OBJ_POINTER, OBJ_UNLINK, ao2_container::version, and WITH_DATA.
Referenced by __ao2_callback(), __ao2_callback_data(), __ao2_callback_data_debug(), and __ao2_callback_debug().
00599 { 00600 int i, start, last; /* search boundaries */ 00601 void *ret = NULL; 00602 ao2_callback_fn *cb_default = NULL; 00603 ao2_callback_data_fn *cb_withdata = NULL; 00604 struct ao2_container *multi_container = NULL; 00605 struct ao2_iterator *multi_iterator = NULL; 00606 00607 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00608 return NULL; 00609 00610 /* 00611 * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA 00612 * turned off. This if statement checks for the special condition 00613 * where multiple items may need to be returned. 00614 */ 00615 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00616 /* we need to return an ao2_iterator with the results, 00617 * as there could be more than one. the iterator will 00618 * hold the only reference to a container that has all the 00619 * matching objects linked into it, so when the iterator 00620 * is destroyed, the container will be automatically 00621 * destroyed as well. 00622 */ 00623 if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) { 00624 return NULL; 00625 } 00626 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) { 00627 ao2_ref(multi_container, -1); 00628 return NULL; 00629 } 00630 } 00631 00632 /* override the match function if necessary */ 00633 if (cb_fn == NULL) { /* if NULL, match everything */ 00634 if (type == WITH_DATA) { 00635 cb_withdata = cb_true_data; 00636 } else { 00637 cb_default = cb_true; 00638 } 00639 } else { 00640 /* We do this here to avoid the per object casting penalty (even though 00641 that is probably optimized away anyway). */ 00642 if (type == WITH_DATA) { 00643 cb_withdata = cb_fn; 00644 } else { 00645 cb_default = cb_fn; 00646 } 00647 } 00648 00649 /* 00650 * XXX this can be optimized. 00651 * If we have a hash function and lookup by pointer, 00652 * run the hash function. Otherwise, scan the whole container 00653 * (this only for the time being. We need to optimize this.) 00654 */ 00655 if ((flags & (OBJ_POINTER | OBJ_KEY))) /* we know hash can handle this case */ 00656 start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets; 00657 else /* don't know, let's scan all buckets */ 00658 start = i = -1; /* XXX this must be fixed later. */ 00659 00660 /* determine the search boundaries: i..last-1 */ 00661 if (i < 0) { 00662 start = i = 0; 00663 last = c->n_buckets; 00664 } else if ((flags & OBJ_CONTINUE)) { 00665 last = c->n_buckets; 00666 } else { 00667 last = i + 1; 00668 } 00669 00670 00671 if (!(flags & OBJ_NOLOCK)) { 00672 ao2_lock(c); /* avoid modifications to the content */ 00673 } 00674 00675 for (; i < last ; i++) { 00676 /* scan the list with prev-cur pointers */ 00677 struct bucket_entry *cur; 00678 00679 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00680 int match = (CMP_MATCH | CMP_STOP); 00681 00682 if (type == WITH_DATA) { 00683 match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags); 00684 } else { 00685 match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags); 00686 } 00687 00688 /* we found the object, performing operations according flags */ 00689 if (match == 0) { /* no match, no stop, continue */ 00690 continue; 00691 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00692 i = last; 00693 break; 00694 } 00695 00696 /* we have a match (CMP_MATCH) here */ 00697 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00698 /* it is important to handle this case before the unlink */ 00699 ret = EXTERNAL_OBJ(cur->astobj); 00700 if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) { 00701 if (tag) 00702 __ao2_ref_debug(ret, 1, tag, file, line, funcname); 00703 else 00704 __ao2_ref(ret, 1); 00705 } 00706 } 00707 00708 /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off, 00709 * link the object into the container that will hold the results. 00710 */ 00711 if (ret && (multi_container != NULL)) { 00712 if (tag) { 00713 __ao2_link_debug(multi_container, ret, flags, tag, file, line, funcname); 00714 } else { 00715 __ao2_link(multi_container, ret, flags); 00716 } 00717 ret = NULL; 00718 } 00719 00720 if (flags & OBJ_UNLINK) { /* must unlink */ 00721 /* we are going to modify the container, so update version */ 00722 ast_atomic_fetchadd_int(&c->version, 1); 00723 AST_LIST_REMOVE_CURRENT(entry); 00724 /* update number of elements */ 00725 ast_atomic_fetchadd_int(&c->elements, -1); 00726 00727 /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container 00728 * must be decremented. 00729 * - When unlinking with OBJ_MULTIPLE the ref from the original container 00730 * must be decremented regardless if OBJ_NODATA is used. This is because the result is 00731 * returned in a new container that already holds its own ref for the object. If the ref 00732 * from the original container is not accounted for here a memory leak occurs. */ 00733 if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) { 00734 if (tag) 00735 __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname); 00736 else 00737 __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1); 00738 } 00739 ast_free(cur); /* free the link record */ 00740 } 00741 00742 if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) { 00743 /* We found our only (or last) match, so force an exit from 00744 the outside loop. */ 00745 i = last; 00746 break; 00747 } 00748 } 00749 AST_LIST_TRAVERSE_SAFE_END; 00750 00751 if (ret) { 00752 break; 00753 } 00754 00755 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00756 /* Move to the beginning to ensure we check every bucket */ 00757 i = -1; 00758 last = start; 00759 } 00760 } 00761 00762 if (!(flags & OBJ_NOLOCK)) { 00763 ao2_unlock(c); 00764 } 00765 00766 /* if multi_container was created, we are returning multiple objects */ 00767 if (multi_container != NULL) { 00768 *multi_iterator = ao2_iterator_init(multi_container, 00769 AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD); 00770 ao2_ref(multi_container, -1); 00771 return multi_iterator; 00772 } else { 00773 return ret; 00774 } 00775 }
| static struct ao2_container* internal_ao2_container_alloc | ( | struct ao2_container * | c, | |
| const unsigned int | n_buckets, | |||
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [static, read] |
Definition at line 408 of file astobj2.c.
References ast_atomic_fetchadd_int(), ao2_container::cmp_fn, ao2_container::hash_fn, hash_zero(), ao2_container::n_buckets, and ao2_container::version.
00410 { 00411 /* XXX maybe consistency check on arguments ? */ 00412 /* compute the container size */ 00413 00414 if (!c) 00415 return NULL; 00416 00417 c->version = 1; /* 0 is a reserved value here */ 00418 c->n_buckets = hash_fn ? n_buckets : 1; 00419 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00420 c->cmp_fn = cmp_fn; 00421 00422 #ifdef AO2_DEBUG 00423 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00424 #endif 00425 00426 return c; 00427 }
| static struct ao2_container* internal_ao2_container_alloc | ( | struct ao2_container * | c, | |
| const uint | n_buckets, | |||
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [static, read] |
Referenced by __ao2_container_alloc(), and __ao2_container_alloc_debug().
| static void * internal_ao2_iterator_next | ( | struct ao2_iterator * | a, | |
| struct bucket_entry ** | q | |||
| ) | [static] |
Definition at line 852 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, ao2_lock, ast_atomic_fetchadd_int(), ast_free, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_TRAVERSE, bucket_entry::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, bucket_entry::version, ao2_iterator::version, and ao2_container::version.
Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().
00853 { 00854 int lim; 00855 struct bucket_entry *p = NULL; 00856 void *ret = NULL; 00857 00858 *q = NULL; 00859 00860 if (INTERNAL_OBJ(a->c) == NULL) 00861 return NULL; 00862 00863 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00864 ao2_lock(a->c); 00865 00866 /* optimization. If the container is unchanged and 00867 * we have a pointer, try follow it 00868 */ 00869 if (a->c->version == a->c_version && (p = a->obj)) { 00870 if ((p = AST_LIST_NEXT(p, entry))) 00871 goto found; 00872 /* nope, start from the next bucket */ 00873 a->bucket++; 00874 a->version = 0; 00875 a->obj = NULL; 00876 } 00877 00878 lim = a->c->n_buckets; 00879 00880 /* Browse the buckets array, moving to the next 00881 * buckets if we don't find the entry in the current one. 00882 * Stop when we find an element with version number greater 00883 * than the current one (we reset the version to 0 when we 00884 * switch buckets). 00885 */ 00886 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00887 /* scan the current bucket */ 00888 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00889 if (p->version > a->version) 00890 goto found; 00891 } 00892 } 00893 00894 found: 00895 if (p) { 00896 ret = EXTERNAL_OBJ(p->astobj); 00897 if (a->flags & AO2_ITERATOR_UNLINK) { 00898 /* we are going to modify the container, so update version */ 00899 ast_atomic_fetchadd_int(&a->c->version, 1); 00900 AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry); 00901 /* update number of elements */ 00902 ast_atomic_fetchadd_int(&a->c->elements, -1); 00903 a->version = 0; 00904 a->obj = NULL; 00905 a->c_version = a->c->version; 00906 ast_free(p); 00907 } else { 00908 a->version = p->version; 00909 a->obj = p; 00910 a->c_version = a->c->version; 00911 /* inc refcount of returned object */ 00912 *q = p; 00913 } 00914 } 00915 00916 return ret; 00917 }
| static struct bucket_entry * internal_ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| int | flags, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [static, read] |
Definition at line 478 of file astobj2.c.
References ao2_lock, ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_entry::astobj, INTERNAL_OBJ(), OBJ_NOLOCK, OBJ_POINTER, and bucket_entry::version.
Referenced by __ao2_link(), and __ao2_link_debug().
00479 { 00480 int i; 00481 /* create a new list entry */ 00482 struct bucket_entry *p; 00483 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00484 00485 if (obj == NULL) 00486 return NULL; 00487 00488 if (INTERNAL_OBJ(c) == NULL) 00489 return NULL; 00490 00491 p = ast_calloc(1, sizeof(*p)); 00492 if (!p) 00493 return NULL; 00494 00495 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00496 00497 if (!(flags & OBJ_NOLOCK)) { 00498 ao2_lock(c); 00499 } 00500 i %= c->n_buckets; 00501 p->astobj = obj; 00502 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00503 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00504 ast_atomic_fetchadd_int(&c->elements, 1); 00505 00506 /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */ 00507 return p; 00508 }
| static int internal_ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) | [static] |
Definition at line 240 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_free, ast_log(), ast_mutex_destroy, __priv_data::data_size, __priv_data::destructor_fn, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by __ao2_ref(), and __ao2_ref_debug().
00241 { 00242 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00243 int current_value; 00244 int ret; 00245 00246 if (obj == NULL) 00247 return -1; 00248 00249 /* if delta is 0, just return the refcount */ 00250 if (delta == 0) 00251 return (obj->priv_data.ref_counter); 00252 00253 /* we modify with an atomic operation the reference counter */ 00254 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00255 current_value = ret + delta; 00256 00257 #ifdef AO2_DEBUG 00258 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00259 #endif 00260 00261 /* this case must never happen */ 00262 if (current_value < 0) 00263 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00264 00265 if (current_value <= 0) { /* last reference, destroy the object */ 00266 if (obj->priv_data.destructor_fn != NULL) { 00267 obj->priv_data.destructor_fn(user_data); 00268 } 00269 00270 ast_mutex_destroy(&obj->priv_data.lock); 00271 #ifdef AO2_DEBUG 00272 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00273 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00274 #endif 00275 /* for safety, zero-out the astobj2 header and also the 00276 * first word of the user-data, which we make sure is always 00277 * allocated. */ 00278 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00279 ast_free(obj); 00280 } 00281 00282 return ret; 00283 }
| static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [static, read] |
convert from a pointer _p to a user-defined object
Definition at line 105 of file astobj2.c.
References AO2_MAGIC, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.
Referenced by __ao2_lock(), __ao2_ref(), __ao2_ref_debug(), __ao2_trylock(), __ao2_unlink(), __ao2_unlink_debug(), __ao2_unlock(), ao2_object_get_lockaddr(), internal_ao2_callback(), internal_ao2_iterator_next(), internal_ao2_link(), and internal_ao2_ref().
00106 { 00107 struct astobj2 *p; 00108 00109 if (!user_data) { 00110 ast_log(LOG_ERROR, "user_data is NULL\n"); 00111 return NULL; 00112 } 00113 00114 p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); 00115 if (AO2_MAGIC != (p->priv_data.magic) ) { 00116 ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p); 00117 p = NULL; 00118 } 00119 00120 return p; 00121 }
1.5.6