Mon Oct 8 12:39:11 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 <execinfo.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 N1   20
#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, char *tag, const char *file, int line, const char *funcname, int ref_debug)
void * __ao2_callback (struct ao2_container *c, const 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, char *tag, char *file, int line, const char *funcname)
void * __ao2_callback_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
ao2_container__ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
ao2_container__ao2_container_alloc_debug (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname, int ref_debug)
void * __ao2_find (struct ao2_container *c, void *arg, enum search_flags flags)
void * __ao2_find_debug (struct ao2_container *c, void *arg, enum search_flags flags, 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, char *tag, char *file, int line, const char *funcname)
void * __ao2_link (struct ao2_container *c, void *user_data)
void * __ao2_link_debug (struct ao2_container *c, void *user_data, 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, 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)
void * __ao2_unlink_debug (struct ao2_container *c, void *user_data, 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.
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, 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, 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 56 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 138 of file astobj2.c.

Referenced by internal_ao2_alloc(), and internal_ao2_callback().

#define N1   20

Referenced by ao2_bt().

#define REF_FILE   "/tmp/refs"

Definition at line 33 of file astobj2.c.

Referenced by __ao2_alloc_debug(), and __ao2_ref_debug().


Enumeration Type Documentation

enum ao2_callback_type

Enumerator:
DEFAULT 
WITH_DATA 

Definition at line 128 of file astobj2.c.

00128                        {
00129    DEFAULT,
00130    WITH_DATA,
00131 };


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,
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,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 770 of file astobj2.c.

References ao2_iterator::c, DEFAULT, and internal_ao2_callback().

Referenced by __ao2_find(), __ao2_unlink(), and container_destruct().

00772 {
00773    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
00774 }

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 784 of file astobj2.c.

References ao2_iterator::c, internal_ao2_callback(), and WITH_DATA.

00786 {
00787    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
00788 }

void* __ao2_callback_data_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 776 of file astobj2.c.

References ao2_iterator::c, internal_ao2_callback(), and WITH_DATA.

00780 {
00781    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
00782 }

void* __ao2_callback_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 762 of file astobj2.c.

References ao2_iterator::c, DEFAULT, and internal_ao2_callback().

Referenced by __ao2_find_debug(), __ao2_unlink_debug(), and container_destruct_debug().

00766 {
00767    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
00768 }

struct ao2_container* __ao2_container_alloc ( const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
)

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,
char *  tag,
char *  file,
int  line,
const char *  funcname,
int  ref_debug 
)

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,
void *  arg,
enum search_flags  flags 
)

Definition at line 798 of file astobj2.c.

References __ao2_callback(), ao2_iterator::c, and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

00799 {
00800    return __ao2_callback(c, flags, c->cmp_fn, arg);
00801 }

void* __ao2_find_debug ( struct ao2_container c,
void *  arg,
enum search_flags  flags,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

the find function just invokes the default callback with some reasonable flags.

Definition at line 793 of file astobj2.c.

References __ao2_callback_debug(), ao2_iterator::c, and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

00794 {
00795    return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
00796 }

void* __ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 919 of file astobj2.c.

References __ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().

00920 {
00921    struct bucket_entry *p = NULL;
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(ret, 1);
00929    }
00930 
00931    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00932       ao2_unlock(a->c);
00933 
00934    return ret;
00935 }

void* __ao2_iterator_next_debug ( struct ao2_iterator a,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 901 of file astobj2.c.

References __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().

00902 {
00903    struct bucket_entry *p;
00904    void *ret = NULL;
00905 
00906    ret = internal_ao2_iterator_next(a, &p);
00907    
00908    if (p) {
00909       /* inc refcount of returned object */
00910       __ao2_ref_debug(ret, 1, tag, file, line, funcname);
00911    }
00912 
00913    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00914       ao2_unlock(a->c);
00915 
00916    return ret;
00917 }

void* __ao2_link ( struct ao2_container c,
void *  user_data 
)

Definition at line 519 of file astobj2.c.

References __ao2_ref(), ao2_unlock, and internal_ao2_link().

Referenced by internal_ao2_callback().

00520 {
00521    struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00522 
00523    if (p) {
00524       __ao2_ref(user_data, +1);
00525       ao2_unlock(c);
00526    }
00527    return p;
00528 }

void* __ao2_link_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 508 of file astobj2.c.

References __ao2_ref_debug(), ao2_unlock, and internal_ao2_link().

Referenced by internal_ao2_callback().

00509 {
00510    struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname);
00511 
00512    if (p) {
00513       __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
00514       ao2_unlock(c);
00515    }
00516    return p;
00517 }

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 151 of file astobj2.c.

References __ast_pthread_mutex_lock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

00152 {
00153    struct astobj2 *p = INTERNAL_OBJ(user_data);
00154 
00155    if (p == NULL)
00156       return -1;
00157 
00158 #ifdef AO2_DEBUG
00159    ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00160 #endif
00161 
00162    return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
00163 }

int __ao2_ref ( void *  user_data,
const int  delta 
)

Definition at line 235 of file astobj2.c.

References internal_ao2_ref().

Referenced by __ao2_iterator_next(), __ao2_link(), cd_cb(), and internal_ao2_callback().

00236 {
00237    return internal_ao2_ref(user_data, delta);
00238 }

int __ao2_ref_debug ( void *  user_data,
const int  delta,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 210 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().

00211 {
00212    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00213    
00214    if (obj == NULL)
00215       return -1;
00216 
00217    if (delta != 0) {
00218       FILE *refo = fopen(REF_FILE, "a");
00219       if (refo) {
00220          fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"),
00221             delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1);
00222          fclose(refo);
00223       }
00224    }
00225    if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
00226       FILE *refo = fopen(REF_FILE, "a");
00227       if (refo) {
00228          fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
00229          fclose(refo);
00230       }
00231    }
00232    return internal_ao2_ref(user_data, delta);
00233 }

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 179 of file astobj2.c.

References __ast_pthread_mutex_trylock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

00180 {
00181    struct astobj2 *p = INTERNAL_OBJ(user_data);
00182    int ret;
00183    
00184    if (p == NULL)
00185       return -1;
00186    ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
00187 
00188 #ifdef AO2_DEBUG
00189    if (!ret)
00190       ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00191 #endif
00192    return ret;
00193 }

void* __ao2_unlink ( struct ao2_container c,
void *  user_data 
)

Definition at line 553 of file astobj2.c.

References __ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.

00554 {
00555    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00556       return NULL;
00557 
00558    __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
00559 
00560    return NULL;
00561 }

void* __ao2_unlink_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 542 of file astobj2.c.

References __ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.

00544 {
00545    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00546       return NULL;
00547 
00548    __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
00549 
00550    return NULL;
00551 }

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 165 of file astobj2.c.

References __ast_pthread_mutex_unlock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

00166 {
00167    struct astobj2 *p = INTERNAL_OBJ(user_data);
00168 
00169    if (p == NULL)
00170       return -1;
00171 
00172 #ifdef AO2_DEBUG
00173    ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00174 #endif
00175 
00176    return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
00177 }

void ao2_bt ( void   ) 

Definition at line 88 of file astobj2.c.

References ast_bt_get_symbols(), ast_verbose, free, and N1.

00089 {
00090    int c, i;
00091 #define N1  20
00092    void *addresses[N1];
00093    char **strings;
00094 
00095    c = backtrace(addresses, N1);
00096    strings = ast_bt_get_symbols(addresses,c);
00097    ast_verbose("backtrace returned: %d\n", c);
00098    for(i = 0; i < c; i++) {
00099       ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
00100    }
00101    free(strings);
00102 }

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(), ast_active_channels(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_tone_zone_count(), 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_monitor(), do_timing(), endelm(), get_unused_callno(), handle_cli_iax2_show_callno_limits(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), locals_show(), lock_broker(), match_filter(), meetme_data_provider_get(), pthread_timer_open(), queue_exec(), queue_function_qac(), 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 821 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_meetmelist(), alias_show(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), 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_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_get_xml_add_child(), 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_session(), find_session_by_nonce(), free_members(), get_member_status(), 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(), kill_duplicate_offers(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), 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_qac(), 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(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

00822 {
00823    ao2_ref(i->c, -1);
00824    if (i->flags & AO2_ITERATOR_MALLOCD) {
00825       ast_free(i);
00826    } else {
00827       i->c = NULL;
00828    }
00829 }

struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
)

Create an iterator for a container.

initialize an iterator so we start from the first object

Definition at line 806 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(), action_meetmelist(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), 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_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_get_xml_add_child(), 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_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_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(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), 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_qac(), 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(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

00807 {
00808    struct ao2_iterator a = {
00809       .c = c,
00810       .flags = flags
00811    };
00812 
00813    ao2_ref(c, +1);
00814    
00815    return a;
00816 }

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 533 of file astobj2.c.

References CMP_MATCH, and CMP_STOP.

00534 {
00535    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00536 }

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 195 of file astobj2.c.

References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

00196 {
00197    struct astobj2 *p = INTERNAL_OBJ(obj);
00198    
00199    if (p == NULL)
00200       return NULL;
00201 
00202    return &p->priv_data.lock;
00203 }

int astobj2_init ( void   ) 

Provided by astobj2.c

Definition at line 1125 of file astobj2.c.

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

01126 {
01127 #ifdef AO2_DEBUG
01128    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01129 #endif
01130 
01131    return 0;
01132 }

static int cb_true ( void *  user_data,
void *  arg,
int  flags 
) [static]

special callback that matches all

Definition at line 566 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

00567 {
00568    return CMP_MATCH;
00569 }

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 574 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

00575 {
00576    return CMP_MATCH;
00577 }

static int cd_cb ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 940 of file astobj2.c.

References __ao2_ref().

Referenced by container_destruct().

00941 {
00942    __ao2_ref(obj, -1);
00943    return 0;
00944 }

static int cd_cb_debug ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 946 of file astobj2.c.

References __ao2_ref_debug().

Referenced by container_destruct_debug().

00947 {
00948    __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
00949    return 0;
00950 }

static void container_destruct ( void *  c  )  [static]

Definition at line 952 of file astobj2.c.

References __ao2_callback(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), ao2_container::n_buckets, and OBJ_UNLINK.

Referenced by __ao2_container_alloc().

00953 {
00954    struct ao2_container *c = _c;
00955    int i;
00956 
00957    __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
00958 
00959    for (i = 0; i < c->n_buckets; i++) {
00960       struct bucket_entry *current;
00961 
00962       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00963          ast_free(current);
00964       }
00965    }
00966 
00967 #ifdef AO2_DEBUG
00968    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00969 #endif
00970 }

static void container_destruct_debug ( void *  c  )  [static]

Definition at line 972 of file astobj2.c.

References __ao2_callback_debug(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb_debug(), ao2_container::n_buckets, and OBJ_UNLINK.

Referenced by __ao2_container_alloc_debug().

00973 {
00974    struct ao2_container *c = _c;
00975    int i;
00976 
00977    __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
00978 
00979    for (i = 0; i < c->n_buckets; i++) {
00980       struct bucket_entry *current;
00981 
00982       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00983          ast_free(current);
00984       }
00985    }
00986 
00987 #ifdef AO2_DEBUG
00988    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00989 #endif
00990 }

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, and EXTERNAL_OBJ.

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,
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 587 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, ao2_container::buckets, ao2_iterator::c, 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_MULTIPLE, OBJ_NODATA, 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().

00590 {
00591    int i, start, last;  /* search boundaries */
00592    void *ret = NULL;
00593    ao2_callback_fn *cb_default = NULL;
00594    ao2_callback_data_fn *cb_withdata = NULL;
00595    struct ao2_container *multi_container = NULL;
00596    struct ao2_iterator *multi_iterator = NULL;
00597 
00598    if (INTERNAL_OBJ(c) == NULL)  /* safety check on the argument */
00599       return NULL;
00600 
00601    /*
00602     * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
00603     * turned off.  This if statement checks for the special condition
00604     * where multiple items may need to be returned.
00605     */
00606    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
00607       /* we need to return an ao2_iterator with the results,
00608        * as there could be more than one. the iterator will
00609        * hold the only reference to a container that has all the
00610        * matching objects linked into it, so when the iterator
00611        * is destroyed, the container will be automatically
00612        * destroyed as well.
00613        */
00614       if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) {
00615          return NULL;
00616       }
00617       if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
00618          ao2_ref(multi_container, -1);
00619          return NULL;
00620       }
00621    }
00622 
00623    /* override the match function if necessary */
00624    if (cb_fn == NULL) { /* if NULL, match everything */
00625       if (type == WITH_DATA) {
00626          cb_withdata = cb_true_data;
00627       } else {
00628          cb_default = cb_true;
00629       }
00630    } else {
00631       /* We do this here to avoid the per object casting penalty (even though
00632          that is probably optimized away anyway). */
00633       if (type == WITH_DATA) {
00634          cb_withdata = cb_fn;
00635       } else {
00636          cb_default = cb_fn;
00637       }
00638    }
00639 
00640    /*
00641     * XXX this can be optimized.
00642     * If we have a hash function and lookup by pointer,
00643     * run the hash function. Otherwise, scan the whole container
00644     * (this only for the time being. We need to optimize this.)
00645     */
00646    if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
00647       start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
00648    else        /* don't know, let's scan all buckets */
00649       start = i = -1;      /* XXX this must be fixed later. */
00650 
00651    /* determine the search boundaries: i..last-1 */
00652    if (i < 0) {
00653       start = i = 0;
00654       last = c->n_buckets;
00655    } else if ((flags & OBJ_CONTINUE)) {
00656       last = c->n_buckets;
00657    } else {
00658       last = i + 1;
00659    }
00660 
00661    ao2_lock(c);   /* avoid modifications to the content */
00662 
00663    for (; i < last ; i++) {
00664       /* scan the list with prev-cur pointers */
00665       struct bucket_entry *cur;
00666 
00667       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
00668          int match = (CMP_MATCH | CMP_STOP);
00669 
00670          if (type == WITH_DATA) {
00671             match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
00672          } else {
00673             match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
00674          }
00675 
00676          /* we found the object, performing operations according flags */
00677          if (match == 0) { /* no match, no stop, continue */
00678             continue;
00679          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
00680             i = last;
00681             break;
00682          }
00683 
00684          /* we have a match (CMP_MATCH) here */
00685          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
00686             /* it is important to handle this case before the unlink */
00687             ret = EXTERNAL_OBJ(cur->astobj);
00688             if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
00689                if (tag)
00690                   __ao2_ref_debug(ret, 1, tag, file, line, funcname);
00691                else
00692                   __ao2_ref(ret, 1);
00693             }
00694          }
00695 
00696          /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off, 
00697           * link the object into the container that will hold the results.
00698           */
00699          if (ret && (multi_container != NULL)) {
00700             if (tag) {
00701                __ao2_link_debug(multi_container, ret, tag, file, line, funcname);
00702             } else {
00703                __ao2_link(multi_container, ret);
00704             }
00705             ret = NULL;
00706          }
00707 
00708          if (flags & OBJ_UNLINK) {  /* must unlink */
00709             /* we are going to modify the container, so update version */
00710             ast_atomic_fetchadd_int(&c->version, 1);
00711             AST_LIST_REMOVE_CURRENT(entry);
00712             /* update number of elements */
00713             ast_atomic_fetchadd_int(&c->elements, -1);
00714 
00715             /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
00716              * must be decremented.
00717              * - When unlinking with OBJ_MULTIPLE the ref from the original container
00718              * must be decremented regardless if OBJ_NODATA is used. This is because the result is
00719              * returned in a new container that already holds its own ref for the object. If the ref
00720              * from the original container is not accounted for here a memory leak occurs. */
00721             if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
00722                if (tag)
00723                   __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
00724                else
00725                   __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
00726             }
00727             ast_free(cur); /* free the link record */
00728          }
00729 
00730          if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
00731             /* We found our only (or last) match, so force an exit from
00732                the outside loop. */
00733             i = last;
00734             break;
00735          }
00736       }
00737       AST_LIST_TRAVERSE_SAFE_END;
00738 
00739       if (ret) {
00740          break;
00741       }
00742 
00743       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
00744          /* Move to the beginning to ensure we check every bucket */
00745          i = -1;
00746          last = start;
00747       }
00748    }
00749    ao2_unlock(c);
00750 
00751    /* if multi_container was created, we are returning multiple objects */
00752    if (multi_container != NULL) {
00753       *multi_iterator = ao2_iterator_init(multi_container,
00754                       AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
00755       ao2_ref(multi_container, -1);
00756       return multi_iterator;
00757    } else {
00758       return ret;
00759    }
00760 }

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]

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]

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 834 of file astobj2.c.

References AO2_ITERATOR_DONTLOCK, ao2_lock, AST_LIST_NEXT, AST_LIST_TRAVERSE, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_entry::entry, 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().

00835 {
00836    int lim;
00837    struct bucket_entry *p = NULL;
00838    void *ret = NULL;
00839 
00840    *q = NULL;
00841    
00842    if (INTERNAL_OBJ(a->c) == NULL)
00843       return NULL;
00844 
00845    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00846       ao2_lock(a->c);
00847 
00848    /* optimization. If the container is unchanged and
00849     * we have a pointer, try follow it
00850     */
00851    if (a->c->version == a->c_version && (p = a->obj)) {
00852       if ((p = AST_LIST_NEXT(p, entry)))
00853          goto found;
00854       /* nope, start from the next bucket */
00855       a->bucket++;
00856       a->version = 0;
00857       a->obj = NULL;
00858    }
00859 
00860    lim = a->c->n_buckets;
00861 
00862    /* Browse the buckets array, moving to the next
00863     * buckets if we don't find the entry in the current one.
00864     * Stop when we find an element with version number greater
00865     * than the current one (we reset the version to 0 when we
00866     * switch buckets).
00867     */
00868    for (; a->bucket < lim; a->bucket++, a->version = 0) {
00869       /* scan the current bucket */
00870       AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
00871          if (p->version > a->version)
00872             goto found;
00873       }
00874    }
00875 
00876 found:
00877    if (p) {
00878       ret = EXTERNAL_OBJ(p->astobj);
00879       if (a->flags & AO2_ITERATOR_UNLINK) {
00880          /* we are going to modify the container, so update version */
00881          ast_atomic_fetchadd_int(&a->c->version, 1);
00882          AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
00883          /* update number of elements */
00884          ast_atomic_fetchadd_int(&a->c->elements, -1);
00885          a->version = 0;
00886          a->obj = NULL;
00887          a->c_version = a->c->version;
00888          ast_free(p);
00889       } else {
00890          a->version = p->version;
00891          a->obj = p;
00892          a->c_version = a->c->version;
00893          /* inc refcount of returned object */
00894          *q = p;
00895       }
00896    }
00897 
00898    return ret;
00899 }

static struct bucket_entry * internal_ao2_link ( struct ao2_container c,
void *  user_data,
const char *  file,
int  line,
const char *  func 
) [static]

Definition at line 478 of file astobj2.c.

References ao2_lock, ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_entry::entry, INTERNAL_OBJ(), and OBJ_POINTER.

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    ao2_lock(c);
00498    i %= c->n_buckets;
00499    p->astobj = obj;
00500    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00501    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00502    ast_atomic_fetchadd_int(&c->elements, 1);
00503 
00504    /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
00505    return p;
00506 }

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  )  [inline, static]

convert from a pointer _p to a user-defined object

Returns:
the pointer to the astobj2 structure

Definition at line 110 of file astobj2.c.

References AO2_MAGIC, ast_log(), and LOG_ERROR.

Referenced by __ao2_lock(), __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().

00111 {
00112    struct astobj2 *p;
00113 
00114    if (!user_data) {
00115       ast_log(LOG_ERROR, "user_data is NULL\n");
00116       return NULL;
00117    }
00118 
00119    p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
00120    if (AO2_MAGIC != (p->priv_data.magic) ) {
00121       ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p);
00122       p = NULL;
00123    }
00124 
00125    return p;
00126 }


Generated on Mon Oct 8 12:39:11 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7