Fri Feb 10 06:34:57 2012

Asterisk developer's documentation


astobj2.c File Reference

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"

Include dependency graph for astobj2.c:

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_containerinternal_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_containerinternal_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_entryinternal_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 astobj2INTERNAL_OBJ (void *user_data)
 convert from a pointer _p to a user-defined object


Define Documentation

#define AO2_MAGIC   0xa570b123

Definition at line 51 of file astobj2.c.

Referenced by internal_ao2_alloc(), and INTERNAL_OBJ().

#define EXTERNAL_OBJ ( _p   )     ((_p) == NULL ? NULL : (_p)->user_data)

convert from a pointer _p to an astobj2 object

Returns:
the pointer to the user-defined portion.

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"

Definition at line 28 of file astobj2.c.

Referenced by __ao2_alloc_debug(), and __ao2_ref_debug().


Enumeration Type Documentation

Enumerator:
DEFAULT 
WITH_DATA 

Definition at line 123 of file astobj2.c.

00123                        {
00124    DEFAULT,
00125    WITH_DATA,
00126 };


Function Documentation

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.

Parameters:
a A pointer to the object we want to lock.
Returns:
0 on success, other values on error.

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).

Parameters:
a A pointer to the object we want to lock.
Returns:
0 on success, other values on error.

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.

Parameters:
a A pointer to the object we want unlock.
Returns:
0 on success, other values on error.

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 }

void ao2_bt ( void   ) 

Definition at line 79 of file astobj2.c.

00079 {}

int ao2_container_count ( struct ao2_container c  ) 

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 
)

another convenience function is a callback that matches on address

Definition at line 539 of file astobj2.c.

References CMP_MATCH, and CMP_STOP.

00540 {
00541    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00542 }

void* ao2_object_get_lockaddr ( void *  obj  ) 

Return the lock address of an object.

Parameters:
[in] obj A pointer to the object we want.
Returns:
the address of the lock, else NULL.
This function comes in handy mainly for debugging locking situations, where the locking trace code reports the lock address, this allows you to correlate against object address, to match objects to reported locks.

Since:
1.6.1

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.

Returns:
0

Definition at line 400 of file astobj2.c.

Referenced by internal_ao2_container_alloc().

00401 {
00402    return 0;
00403 }

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.

Returns:
Is a pointer to an object or to a list of object if OBJ_MULTIPLE is specified. Luckily, for debug purposes, the added args (tag, file, line, funcname) aren't an excessive load to the system, as the callback should not be called as often as, say, the ao2_ref func is called.

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]

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

Returns:
the pointer to the astobj2 structure

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 }


Generated on Fri Feb 10 06:34:57 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6