Sat Aug 6 00:39:39 2011

Asterisk developer's documentation


astobj2.c File Reference

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

Go to the source code of this file.

Data Structures

struct  __priv_data
struct  ao2_container
struct  astobj2
struct  bucket
struct  bucket_list

Defines

#define AO2_MAGIC   0xa570b123
#define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
 convert from a pointer _p to an astobj2 object

Functions

void * __ao2_link (struct ao2_container *c, void *user_data, int iax2_hack)
int __ao2_lock (void *user_data, const char *file, const char *func, int line, const char *var)
int __ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var)
int __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var)
void * ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn)
void ao2_bt (void)
void * ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn cb_fn, void *arg)
ao2_containerao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn hash_fn, ao2_callback_fn cmp_fn)
int ao2_container_count (struct ao2_container *c)
void * ao2_find (struct ao2_container *c, void *arg, enum search_flags flags)
void ao2_iterator_destroy (struct ao2_iterator *i)
 Destroy a container iterator.
ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
 Create an iterator for a container.
void * ao2_iterator_next (struct ao2_iterator *a)
int ao2_lock (void *user_data)
int ao2_match_by_addr (void *user_data, void *arg, int flags)
 another convenience function is a callback that matches on address
int ao2_ref (void *user_data, const int delta)
int ao2_trylock (void *user_data)
void * ao2_unlink (struct ao2_container *c, void *user_data)
int ao2_unlock (void *user_data)
int astobj2_init (void)
static int cb_true (void *user_data, void *arg, int flags)
 special callback that matches all
static int cd_cb (void *obj, void *arg, int flag)
static void container_destruct (void *c)
static int hash_zero (const void *user_obj, const int flags)
 always zero hash function
static struct astobj2INTERNAL_OBJ (void *user_data)
 convert from a pointer _p to a user-defined object


Define Documentation

#define AO2_MAGIC   0xa570b123

Definition at line 49 of file astobj2.c.

Referenced by 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 126 of file astobj2.c.

Referenced by ao2_alloc(), and ao2_callback().


Function Documentation

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

Definition at line 425 of file astobj2.c.

References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, bucket_list::entry, and INTERNAL_OBJ().

Referenced by set_config().

00426 {
00427    int i;
00428    /* create a new list entry */
00429    struct bucket_list *p;
00430    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00431    
00432    if (!obj)
00433       return NULL;
00434 
00435    if (INTERNAL_OBJ(c) == NULL)
00436       return NULL;
00437 
00438    p = ast_calloc(1, sizeof(*p));
00439    if (!p)
00440       return NULL;
00441 
00442    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00443 
00444    ao2_lock(c);
00445    i %= c->n_buckets;
00446    p->astobj = obj;
00447    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00448    if (iax2_hack)
00449       AST_LIST_INSERT_HEAD(&c->buckets[i], p, entry);
00450    else
00451       AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00452    ast_atomic_fetchadd_int(&c->elements, 1);
00453    ao2_ref(user_data, +1);
00454    ao2_unlock(c);
00455    
00456    return p;
00457 }

int __ao2_lock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 149 of file astobj2.c.

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

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

int __ao2_trylock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 186 of file astobj2.c.

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

00187 {
00188    struct astobj2 *p = INTERNAL_OBJ(user_data);
00189    int res;
00190 
00191    if (p == NULL)
00192       return -1;
00193 
00194 #ifndef DEBUG_THREADS
00195    res = ast_mutex_trylock(&p->priv_data.lock);
00196 #else
00197    res = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
00198 #endif
00199 
00200 #ifdef AO2_DEBUG
00201    if (!res) {
00202       ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00203    }
00204 #endif
00205 
00206    return res;
00207 }

int __ao2_unlock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 223 of file astobj2.c.

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

00224 {
00225    struct astobj2 *p = INTERNAL_OBJ(user_data);
00226 
00227    if (p == NULL)
00228       return -1;
00229 
00230 #ifdef AO2_DEBUG
00231    ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00232 #endif
00233 
00234 #ifndef DEBUG_THREADS
00235    return ast_mutex_unlock(&p->priv_data.lock);
00236 #else
00237    return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
00238 #endif
00239 }

void* ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn 
)

Definition at line 292 of file astobj2.c.

References AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), and EXTERNAL_OBJ.

Referenced by add_calltoken_ignore(), alloc_queue(), ao2_container_alloc(), ast_add_hint(), build_callno_limits(), build_peer(), build_user(), conf_run(), create_callno_pools(), create_queue_member(), get_filestream(), inprocess_count(), local_alloc(), moh_class_malloc(), new_iax(), peercnt_add(), update_provisional_keepalive(), and xml_translate().

00293 {
00294    /* allocation */
00295    struct astobj2 *obj;
00296 
00297    if (data_size < sizeof(void *))
00298       data_size = sizeof(void *);
00299 
00300    obj = ast_calloc(1, sizeof(*obj) + data_size);
00301 
00302    if (obj == NULL)
00303       return NULL;
00304 
00305    ast_mutex_init(&obj->priv_data.lock);
00306    obj->priv_data.magic = AO2_MAGIC;
00307    obj->priv_data.data_size = data_size;
00308    obj->priv_data.ref_counter = 1;
00309    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00310 
00311 #ifdef AO2_DEBUG
00312    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00313    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00314    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00315 #endif
00316 
00317    /* return a pointer to the user data */
00318    return EXTERNAL_OBJ(obj);
00319 }

void ao2_bt ( void   ) 

Definition at line 77 of file astobj2.c.

00077 {}

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

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.

Definition at line 494 of file astobj2.c.

References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), bucket_list::astobj, ao2_container::buckets, cb_true(), ao2_container::elements, bucket_list::entry, EXTERNAL_OBJ, free, ao2_container::hash_fn, INTERNAL_OBJ(), last, LOG_WARNING, match(), ao2_container::n_buckets, and ao2_container::version.

Referenced by admin_exec(), ao2_find(), ao2_unlink(), ast_moh_destroy(), calltoken_required(), conf_run(), container_destruct(), delete_users(), load_module(), load_moh_classes(), reload_config(), set_config_destroy(), set_peercnt_limit(), and unload_module().

00497 {
00498    int i, start, last;  /* search boundaries */
00499    void *ret = NULL;
00500 
00501    if (INTERNAL_OBJ(c) == NULL)  /* safety check on the argument */
00502       return NULL;
00503 
00504    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
00505       ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
00506       return NULL;
00507    }
00508 
00509    /* override the match function if necessary */
00510 #if 0
00511    /* Removing this slightly changes the meaning of OBJ_POINTER, but makes it
00512     * do what I want it to.  I'd like to hint to ao2_callback that the arg is
00513     * of the same object type, so it can be passed to the hash function.
00514     * However, I don't want to imply that this is the object being searched for. */
00515    if (flags & OBJ_POINTER)
00516       cb_fn = match_by_addr;
00517    else
00518 #endif
00519    if (cb_fn == NULL)   /* if NULL, match everything */
00520       cb_fn = cb_true;
00521    /*
00522     * XXX this can be optimized.
00523     * If we have a hash function and lookup by pointer,
00524     * run the hash function. Otherwise, scan the whole container
00525     * (this only for the time being. We need to optimize this.)
00526     */
00527    if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
00528       start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
00529    else        /* don't know, let's scan all buckets */
00530       start = i = -1;      /* XXX this must be fixed later. */
00531 
00532    /* determine the search boundaries: i..last-1 */
00533    if (i < 0) {
00534       start = i = 0;
00535       last = c->n_buckets;
00536    } else if ((flags & OBJ_CONTINUE)) {
00537       last = c->n_buckets;
00538    } else {
00539       last = i + 1;
00540    }
00541 
00542    ao2_lock(c);   /* avoid modifications to the content */
00543 
00544    for (; i < last ; i++) {
00545       /* scan the list with prev-cur pointers */
00546       struct bucket_list *cur;
00547 
00548       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
00549          int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
00550 
00551          /* we found the object, performing operations according flags */
00552          if (match == 0) { /* no match, no stop, continue */
00553             continue;
00554          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
00555             i = last;
00556             break;
00557          }
00558          /* we have a match (CMP_MATCH) here */
00559          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
00560             /* it is important to handle this case before the unlink */
00561             ret = EXTERNAL_OBJ(cur->astobj);
00562             ao2_ref(ret, 1);
00563          }
00564 
00565          if (flags & OBJ_UNLINK) {  /* must unlink */
00566             struct bucket_list *x = cur;
00567 
00568             /* we are going to modify the container, so update version */
00569             ast_atomic_fetchadd_int(&c->version, 1);
00570             AST_LIST_REMOVE_CURRENT(&c->buckets[i], entry);
00571             /* update number of elements and version */
00572             ast_atomic_fetchadd_int(&c->elements, -1);
00573             ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
00574             free(x); /* free the link record */
00575          }
00576 
00577          if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
00578             /* We found the only match we need */
00579             i = last;   /* force exit from outer loop */
00580             break;
00581          }
00582          if (!(flags & OBJ_NODATA)) {
00583 #if 0 /* XXX to be completed */
00584             /*
00585              * This is the multiple-return case. We need to link
00586              * the object in a list. The refcount is already increased.
00587              */
00588 #endif
00589          }
00590       }
00591       AST_LIST_TRAVERSE_SAFE_END
00592 
00593       if (ret) {
00594          /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */
00595          break;
00596       }
00597 
00598       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
00599          /* Move to the beginning to ensure we check every bucket */
00600          i = -1;
00601          last = start;
00602       }
00603    }
00604    ao2_unlock(c);
00605    return ret;
00606 }

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

Definition at line 379 of file astobj2.c.

References ao2_alloc(), ast_atomic_fetchadd_int(), ao2_container::cmp_fn, container_destruct(), ao2_container::hash_fn, hash_zero(), ao2_container::n_buckets, and ao2_container::version.

Referenced by ast_pbx_init(), build_conf(), create_callno_pools(), init_queue(), load_module(), load_objects(), and xml_translate().

00381 {
00382    /* XXX maybe consistency check on arguments ? */
00383    /* compute the container size */
00384    size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
00385 
00386    struct ao2_container *c = ao2_alloc(container_size, container_destruct);
00387 
00388    if (!c)
00389       return NULL;
00390    
00391    c->version = 1;   /* 0 is a reserved value here */
00392    c->n_buckets = n_buckets;
00393    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00394    c->cmp_fn = cmp_fn;
00395 
00396 #ifdef AO2_DEBUG
00397    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00398 #endif
00399 
00400    return c;
00401 }

int ao2_container_count ( struct ao2_container c  ) 

return the number of elements in the container

Definition at line 406 of file astobj2.c.

References ao2_container::elements.

Referenced by __queues_show(), get_unused_callno(), handle_show_hints(), and locals_show().

00407 {
00408    return c->elements;
00409 }

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

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

Definition at line 611 of file astobj2.c.

References ao2_callback(), and ao2_container::cmp_fn.

Referenced by __find_callno(), add_calltoken_ignore(), admin_exec(), ast_add_hint(), ast_change_hint(), ast_merge_contexts_and_delete(), ast_remove_hint(), authenticate_request(), authenticate_verify(), build_callno_limits(), build_peer(), build_user(), compare_weight(), conf_run(), find_peer(), find_user(), get_mohbyname(), get_unused_callno(), iax2_destroy_helper(), inprocess_count(), meetmemute(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), reload_queues(), remove_from_queue(), rt_handle_member_record(), sched_delay_remove(), and xml_translate().

00612 {
00613    return ao2_callback(c, flags, c->cmp_fn, arg);
00614 }

void ao2_iterator_destroy ( struct ao2_iterator i  ) 

Destroy a container iterator.

destroy an iterator

Definition at line 634 of file astobj2.c.

References ao2_ref(), and ao2_iterator::c.

Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().

00635 {
00636    ao2_ref(i->c, -1);
00637    i->c = NULL;
00638 }

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

References ao2_ref(), and ao2_iterator::flags.

Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().

00620 {
00621    struct ao2_iterator a = {
00622       .c = c,
00623       .flags = flags
00624    };
00625 
00626    ao2_ref(c, +1);
00627    
00628    return a;
00629 }

void* ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 643 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_list::entry, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, ao2_container::version, ao2_iterator::version, and bucket_list::version.

Referenced by __iax2_show_peers(), __queues_show(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), authenticate_reply(), check_access(), cli_files_show(), complete_iax2_show_peer(), complete_meetmecmd(), complete_queue_remove_member(), conf_queue_dtmf(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), iax2_getpeername(), iax2_getpeertrunk(), iax2_show_callnumber_usage(), iax2_show_users(), interface_exists(), interface_exists_global(), locals_show(), manager_queues_status(), meetme_cmd(), moh_classes_show(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), try_calling(), unload_module(), update_realtime_members(), and update_status().

00644 {
00645    int lim;
00646    struct bucket_list *p = NULL;
00647    void *ret = NULL;
00648 
00649    if (INTERNAL_OBJ(a->c) == NULL)
00650       return NULL;
00651 
00652    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00653       ao2_lock(a->c);
00654 
00655    /* optimization. If the container is unchanged and
00656     * we have a pointer, try follow it
00657     */
00658    if (a->c->version == a->c_version && (p = a->obj) ) {
00659       if ( (p = AST_LIST_NEXT(p, entry)) )
00660          goto found;
00661       /* nope, start from the next bucket */
00662       a->bucket++;
00663       a->version = 0;
00664       a->obj = NULL;
00665    }
00666 
00667    lim = a->c->n_buckets;
00668 
00669    /* Browse the buckets array, moving to the next
00670     * buckets if we don't find the entry in the current one.
00671     * Stop when we find an element with version number greater
00672     * than the current one (we reset the version to 0 when we
00673     * switch buckets).
00674     */
00675    for (; a->bucket < lim; a->bucket++, a->version = 0) {
00676       /* scan the current bucket */
00677       AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
00678          if (p->version > a->version)
00679             goto found;
00680       }
00681    }
00682 
00683 found:
00684    if (p) {
00685       a->version = p->version;
00686       a->obj = p;
00687       a->c_version = a->c->version;
00688       ret = EXTERNAL_OBJ(p->astobj);
00689       /* inc refcount of returned object */
00690       ao2_ref(ret, 1);
00691    }
00692 
00693    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00694       ao2_unlock(a->c);
00695 
00696    return ret;
00697 }

int ao2_lock ( void *  user_data  ) 

Definition at line 135 of file astobj2.c.

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

Referenced by __ao2_link(), __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), conf_run(), find_queue_by_name_rt(), get_member_status(), get_unused_callno(), inprocess_count(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), local_answer(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_write(), locals_show(), manager_queues_status(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_member_count(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), try_calling(), update_queue(), update_realtime_members(), and update_status().

00136 {
00137    struct astobj2 *p = INTERNAL_OBJ(user_data);
00138 
00139    if (p == NULL)
00140       return -1;
00141 
00142 #ifdef AO2_DEBUG
00143    ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00144 #endif
00145 
00146    return ast_mutex_lock(&p->priv_data.lock);
00147 }

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

Referenced by ao2_unlink().

00463 {
00464    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00465 }

int ao2_ref ( void *  user_data,
const int  delta 
)

Definition at line 244 of file astobj2.c.

References ast_atomic_fetchadd_int(), ast_log(), ast_mutex_destroy(), __priv_data::data_size, __priv_data::destructor_fn, free, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.

Referenced by __ao2_link(), __find_callno(), __queues_show(), __unload_module(), add_calltoken_ignore(), add_to_queue(), admin_exec(), announce_thread(), ao2_callback(), ao2_iterator_destroy(), ao2_iterator_init(), ast_add_hint(), ast_change_hint(), ast_closestream(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), build_conf(), calltoken_required(), cd_cb(), compare_weight(), complete_meetmecmd(), complete_queue_remove_member(), conf_free(), conf_queue_dtmf(), conf_run(), create_callno_pools(), destroy_queue(), dump_queue_members(), free_members(), get_member_status(), handle_show_hints(), hangupcalls(), iax2_destroy(), iax2_show_callnumber_usage(), inprocess_count(), insert_entry(), interface_exists(), interface_exists_global(), load_module(), load_objects(), local_answer(), local_digit_begin(), local_digit_end(), local_hangup(), local_indicate(), local_request(), local_sendhtml(), local_sendtext(), local_write(), locals_show(), manager_queues_status(), meetme_cmd(), meetmemute(), new_iax(), num_available_members(), peer_ref(), peer_unref(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), peercnt_remove_cb(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_member_count(), reload_queues(), remove_from_queue(), remove_provisional_keepalive_sched(), remove_queue(), replace_callno(), rt_handle_member_record(), sched_delay_remove(), send_provisional_keepalive_full(), set_member_paused(), set_peercnt_limit(), try_calling(), unload_module(), unref_provisional_keepalive(), update_provisional_keepalive(), update_realtime_members(), update_status(), user_ref(), user_unref(), and xml_translate().

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

int ao2_trylock ( void *  user_data  ) 

Definition at line 167 of file astobj2.c.

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

Referenced by local_hangup(), local_queue_frame(), and local_setoption().

00168 {
00169    struct astobj2 *p = INTERNAL_OBJ(user_data);
00170    int res;
00171 
00172    if (p == NULL)
00173       return -1;
00174 
00175    res = ast_mutex_trylock(&p->priv_data.lock);
00176 
00177 #ifdef AO2_DEBUG
00178    if (!res) {
00179       ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00180    }
00181 #endif
00182 
00183    return res;
00184 }

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

Definition at line 471 of file astobj2.c.

References ao2_callback(), ao2_match_by_addr(), and INTERNAL_OBJ().

Referenced by ast_remove_hint(), build_user(), free_members(), iax2_prune_realtime(), local_hangup(), local_request(), peercnt_remove(), prune_users(), reload_queues(), remove_by_peercallno(), remove_by_transfercallno(), remove_from_queue(), unlink_peer(), and update_realtime_members().

00472 {
00473    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00474       return NULL;
00475 
00476    ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
00477 
00478    return NULL;
00479 }

int ao2_unlock ( void *  user_data  ) 

Definition at line 209 of file astobj2.c.

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

Referenced by __ao2_link(), __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_hint_state_changed(), ast_merge_contexts_and_delete(), ast_remove_hint(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), conf_run(), find_queue_by_name_rt(), get_member_status(), get_unused_callno(), inprocess_count(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), local_answer(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_setoption(), local_write(), locals_show(), manager_queues_status(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_queuemembercount(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_member_count(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), try_calling(), update_queue(), update_realtime_members(), and update_status().

00210 {
00211    struct astobj2 *p = INTERNAL_OBJ(user_data);
00212 
00213    if (p == NULL)
00214       return -1;
00215 
00216 #ifdef AO2_DEBUG
00217    ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00218 #endif
00219 
00220    return ast_mutex_unlock(&p->priv_data.lock);
00221 }

int astobj2_init ( void   ) 

Definition at line 837 of file astobj2.c.

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

00838 {
00839 #ifdef AO2_DEBUG
00840    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
00841 #endif
00842 
00843    return 0;
00844 }

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

special callback that matches all

Definition at line 484 of file astobj2.c.

Referenced by ao2_callback().

00485 {
00486    return CMP_MATCH;
00487 }

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

Definition at line 702 of file astobj2.c.

References ao2_ref().

Referenced by container_destruct().

00703 {
00704    ao2_ref(obj, -1);
00705    return 0;
00706 }

static void container_destruct ( void *  c  )  [static]

Definition at line 708 of file astobj2.c.

References ao2_callback(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_list::entry, and ao2_container::n_buckets.

Referenced by ao2_container_alloc().

00709 {
00710    struct ao2_container *c = _c;
00711    int i;
00712 
00713    ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
00714 
00715    for (i = 0; i < c->n_buckets; i++) {
00716       struct bucket_list *cur;
00717 
00718       while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00719          ast_free(cur);
00720       }
00721    }
00722 
00723 #ifdef AO2_DEBUG
00724    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00725 #endif
00726 }

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

Referenced by ao2_container_alloc().

00371 {
00372    return 0;
00373 }

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

References AO2_MAGIC, ast_log(), and LOG_ERROR.

Referenced by __ao2_link(), __ao2_lock(), __ao2_trylock(), __ao2_unlock(), ao2_callback(), ao2_iterator_next(), ao2_lock(), ao2_ref(), ao2_trylock(), ao2_unlink(), and ao2_unlock().

00104 {
00105    struct astobj2 *p;
00106 
00107    if (!user_data) {
00108       ast_log(LOG_ERROR, "user_data is NULL\n");
00109       return NULL;
00110    }
00111 
00112    p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
00113    if (AO2_MAGIC != (p->priv_data.magic) ) {
00114       ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p);
00115       p = NULL;
00116    }
00117 
00118    return p;
00119 }


Generated on Sat Aug 6 00:39:39 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7