Mon Jun 27 16:51:03 2011

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 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(), and internal_ao2_callback().

#define N1   20

Referenced by ao2_bt().

#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

enum ao2_callback_type

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

References internal_ao2_alloc().

Referenced by __ao2_container_alloc().

00339 {
00340    return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
00341 }

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

00319 {
00320    /* allocation */
00321    void *obj;
00322    FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL;
00323 
00324    if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) {
00325       fclose(refo);
00326       return NULL;
00327    }
00328 
00329    if (refo) {
00330       fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
00331       fclose(refo);
00332    }
00333 
00334    /* return a pointer to the user data */
00335    return obj;
00336 }

void* __ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 766 of file astobj2.c.

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

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

00768 {
00769    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
00770 }

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

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

00782 {
00783    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
00784 }

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

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

00776 {
00777    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
00778 }

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

00762 {
00763    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
00764 }

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

Definition at line 438 of file astobj2.c.

References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().

Referenced by internal_ao2_callback().

00440 {
00441    /* XXX maybe consistency check on arguments ? */
00442    /* compute the container size */
00443 
00444    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00445    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00446    struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
00447 
00448    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00449 }

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

References __ao2_alloc_debug(), container_destruct_debug(), and internal_ao2_container_alloc().

00428 {
00429    /* XXX maybe consistency check on arguments ? */
00430    /* compute the container size */
00431    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00432    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00433    struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
00434 
00435    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00436 }

void* __ao2_find ( struct ao2_container c,
void *  arg,
enum search_flags  flags 
)

Definition at line 794 of file astobj2.c.

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

Referenced by _get_mohbyname().

00795 {
00796    return __ao2_callback(c, flags, c->cmp_fn, arg);
00797 }

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

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

Referenced by _get_mohbyname().

00790 {
00791    return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
00792 }

void* __ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 915 of file astobj2.c.

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

00916 {
00917    struct bucket_entry *p = NULL;
00918    void *ret = NULL;
00919 
00920    ret = internal_ao2_iterator_next(a, &p);
00921    
00922    if (p) {
00923       /* inc refcount of returned object */
00924       __ao2_ref(ret, 1);
00925    }
00926 
00927    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00928       ao2_unlock(a->c);
00929 
00930    return ret;
00931 }

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

Definition at line 897 of file astobj2.c.

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

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

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

Definition at line 515 of file astobj2.c.

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

Referenced by internal_ao2_callback().

00516 {
00517    struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00518 
00519    if (p) {
00520       __ao2_ref(user_data, +1);
00521       ao2_unlock(c);
00522    }
00523    return p;
00524 }

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

Definition at line 504 of file astobj2.c.

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

Referenced by internal_ao2_callback().

00505 {
00506    struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname);
00507 
00508    if (p) {
00509       __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
00510       ao2_unlock(c);
00511    }
00512    return p;
00513 }

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

References internal_ao2_ref(), and INTERNAL_OBJ().

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

00226 {
00227    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00228 
00229    if (obj == NULL)
00230       return -1;
00231 
00232    return internal_ao2_ref(user_data, delta);
00233 }

int __ao2_ref_debug ( void *  user_data,
const int  delta,
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       fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1);
00215       fclose(refo);
00216    }
00217    if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
00218          FILE *refo = fopen(REF_FILE,"a");    
00219          fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);   
00220          fclose(refo);
00221    }
00222    return internal_ao2_ref(user_data, delta);
00223 }

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 
)

Definition at line 549 of file astobj2.c.

References __ao2_callback(), 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    __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
00555 
00556    return NULL;
00557 }

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

Definition at line 538 of file astobj2.c.

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

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

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

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

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

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 454 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(), cc_cli_output_status(), cleanup(), cli_fax_show_sessions(), cli_tps_report(), data_odbc_provider_handler(), data_provider_release(), data_provider_release_all(), do_timing(), endelm(), 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(), and unload_module().

00455 {
00456    return c->elements;
00457 }

void ao2_iterator_destroy ( struct ao2_iterator i  ) 

Destroy a container iterator.

destroy an iterator

Definition at line 817 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(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), compare_weight(), complete_core_id(), complete_core_show_hint(), 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_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_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), 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(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), 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(), 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(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

00818 {
00819    ao2_ref(i->c, -1);
00820    if (i->flags & AO2_ITERATOR_MALLOCD) {
00821       ast_free(i);
00822    } else {
00823       i->c = NULL;
00824    }
00825 }

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 802 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_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(), 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().

00803 {
00804    struct ao2_iterator a = {
00805       .c = c,
00806       .flags = flags
00807    };
00808 
00809    ao2_ref(c, +1);
00810    
00811    return a;
00812 }

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

References CMP_MATCH, and CMP_STOP.

00530 {
00531    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00532 }

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.

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

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

01122 {
01123 #ifdef AO2_DEBUG
01124    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01125 #endif
01126 
01127    return 0;
01128 }

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

special callback that matches all

Definition at line 562 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

00563 {
00564    return CMP_MATCH;
00565 }

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

References CMP_MATCH.

Referenced by internal_ao2_callback().

00571 {
00572    return CMP_MATCH;
00573 }

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

Definition at line 936 of file astobj2.c.

References __ao2_ref().

Referenced by container_destruct().

00937 {
00938    __ao2_ref(obj, -1);
00939    return 0;
00940 }

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

Definition at line 942 of file astobj2.c.

References __ao2_ref_debug().

Referenced by container_destruct_debug().

00943 {
00944    __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
00945    return 0;
00946 }

static void container_destruct ( void *  c  )  [static]

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

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

static void container_destruct_debug ( void *  c  )  [static]

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

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

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

Referenced by internal_ao2_container_alloc().

00397 {
00398    return 0;
00399 }

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

00285 {
00286    /* allocation */
00287    struct astobj2 *obj;
00288 
00289    if (data_size < sizeof(void *))
00290       data_size = sizeof(void *);
00291 
00292 #if defined(__AST_DEBUG_MALLOC)
00293    obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
00294 #else
00295    obj = ast_calloc(1, sizeof(*obj) + data_size);
00296 #endif
00297 
00298    if (obj == NULL)
00299       return NULL;
00300 
00301    ast_mutex_init(&obj->priv_data.lock);
00302    obj->priv_data.magic = AO2_MAGIC;
00303    obj->priv_data.data_size = data_size;
00304    obj->priv_data.ref_counter = 1;
00305    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00306 
00307 #ifdef AO2_DEBUG
00308    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00309    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00310    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00311 #endif
00312 
00313    /* return a pointer to the user data */
00314    return EXTERNAL_OBJ(obj);
00315 }

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

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

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

00406 {
00407    /* XXX maybe consistency check on arguments ? */
00408    /* compute the container size */
00409 
00410    if (!c)
00411       return NULL;
00412    
00413    c->version = 1;   /* 0 is a reserved value here */
00414    c->n_buckets = hash_fn ? n_buckets : 1;
00415    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00416    c->cmp_fn = cmp_fn;
00417 
00418 #ifdef AO2_DEBUG
00419    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00420 #endif
00421 
00422    return c;
00423 }

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

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

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

00475 {
00476    int i;
00477    /* create a new list entry */
00478    struct bucket_entry *p;
00479    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00480 
00481    if (obj == NULL)
00482       return NULL;
00483 
00484    if (INTERNAL_OBJ(c) == NULL)
00485       return NULL;
00486 
00487    p = ast_calloc(1, sizeof(*p));
00488    if (!p)
00489       return NULL;
00490 
00491    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00492 
00493    ao2_lock(c);
00494    i %= c->n_buckets;
00495    p->astobj = obj;
00496    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00497    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00498    ast_atomic_fetchadd_int(&c->elements, 1);
00499 
00500    /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
00501    return p;
00502 }

static int internal_ao2_ref ( void *  user_data,
const int  delta 
) [static]

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

00236 {
00237    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00238    int current_value;
00239    int ret;
00240 
00241    if (obj == NULL)
00242       return -1;
00243 
00244    /* if delta is 0, just return the refcount */
00245    if (delta == 0)
00246       return (obj->priv_data.ref_counter);
00247 
00248    /* we modify with an atomic operation the reference counter */
00249    ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
00250    current_value = ret + delta;
00251 
00252 #ifdef AO2_DEBUG  
00253    ast_atomic_fetchadd_int(&ao2.total_refs, delta);
00254 #endif
00255 
00256    /* this case must never happen */
00257    if (current_value < 0)
00258       ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
00259 
00260    if (current_value <= 0) { /* last reference, destroy the object */
00261       if (obj->priv_data.destructor_fn != NULL) {
00262          obj->priv_data.destructor_fn(user_data);
00263       }
00264 
00265       ast_mutex_destroy(&obj->priv_data.lock);
00266 #ifdef AO2_DEBUG
00267       ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
00268       ast_atomic_fetchadd_int(&ao2.total_objects, -1);
00269 #endif
00270       /* for safety, zero-out the astobj2 header and also the
00271        * first word of the user-data, which we make sure is always
00272        * allocated. */
00273       memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
00274       ast_free(obj);
00275    }
00276 
00277    return ret;
00278 }

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

References AO2_MAGIC, ast_log(), and LOG_ERROR.

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 Mon Jun 27 16:51:03 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7