Wed Oct 28 11:45:50 2009

Asterisk developer's documentation


astobj2.c File Reference

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

Include dependency graph for astobj2.c:

Go to the source code of this file.

Data Structures

struct  __priv_data
struct  ao2_container
struct  astobj2
struct  bucket
struct  bucket_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_alloc (size_t data_size, ao2_destructor_fn destructor_fn)
 Allocate and initialize an object.
void ao2_bt (void)
void * ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
 ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
struct ao2_containerao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
 Allocate and initialize a container with the desired number of buckets.
int ao2_container_count (struct ao2_container *c)
 Returns the number of elements in a container.
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.
struct 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)
void * ao2_link (struct ao2_container *c, void *user_data)
 Add an object to a container.
int ao2_lock (void *user_data)
 Lock an object.
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)
 Reference/unreference an object and return the old refcount.
int ao2_trylock (void *user_data)
 Try locking-- (don't block if fail).
void * ao2_unlink (struct ao2_container *c, void *user_data)
 Remove an object from the container.
int ao2_unlock (void *user_data)
 Unlock an object.
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 50 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 127 of file astobj2.c.

Referenced by ao2_alloc(), ao2_callback(), and ao2_iterator_next().


Function Documentation

void* ao2_alloc ( const size_t  data_size,
ao2_destructor_fn  destructor_fn 
)

Allocate and initialize an object.

Parameters:
data_size The sizeof() of the user-defined structure.
destructor_fn The destructor function (can be NULL)
Returns:
A pointer to user-data.
Allocates a struct astobj2 with sufficient space for the user-defined structure.
Note:
  • storage is zeroed; XXX maybe we want a flag to enable/disable this.
  • the refcount of the object just created is 1
  • the returned pointer cannot be free()'d or realloc()'ed; rather, we just call ao2_ref(o, -1);

Definition at line 248 of file astobj2.c.

References AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, __priv_data::lock, __priv_data::magic, astobj2::priv_data, and __priv_data::ref_counter.

Referenced by add_calltoken_ignore(), alloc_queue(), ao2_container_alloc(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_callno_limits(), build_device(), build_peer(), build_profile(), build_route(), build_user(), conf_run(), create_callno_pools(), create_queue_member(), dialgroup_write(), get_filestream(), get_lock(), moh_class_malloc(), new_iax(), peercnt_add(), set_fn(), sip_alloc(), try_calling(), and xml_translate().

00249 {
00250    /* allocation */
00251    struct astobj2 *obj;
00252 
00253    if (data_size < sizeof(void *))
00254       data_size = sizeof(void *);
00255 
00256    obj = ast_calloc(1, sizeof(*obj) + data_size);
00257 
00258    if (obj == NULL)
00259       return NULL;
00260 
00261    ast_mutex_init(&obj->priv_data.lock);
00262    obj->priv_data.magic = AO2_MAGIC;
00263    obj->priv_data.data_size = data_size;
00264    obj->priv_data.ref_counter = 1;
00265    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00266 
00267 #ifdef AO2_DEBUG
00268    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00269    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00270    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00271 #endif
00272 
00273    /* return a pointer to the user data */
00274    return EXTERNAL_OBJ(obj);
00275 }

void ao2_bt ( void   ) 

Definition at line 78 of file astobj2.c.

00078 {}

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

ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.

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 447 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(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_list::entry, EXTERNAL_OBJ, free, ao2_container::hash_fn, INTERNAL_OBJ(), last, LOG_WARNING, match(), ao2_container::n_buckets, OBJ_CONTINUE, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, and ao2_container::version.

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

00450 {
00451    int i, start, last;  /* search boundaries */
00452    void *ret = NULL;
00453 
00454    if (INTERNAL_OBJ(c) == NULL)  /* safety check on the argument */
00455       return NULL;
00456 
00457    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
00458       ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
00459       return NULL;
00460    }
00461 
00462    /* override the match function if necessary */
00463    if (cb_fn == NULL)   /* if NULL, match everything */
00464       cb_fn = cb_true;
00465    /*
00466     * XXX this can be optimized.
00467     * If we have a hash function and lookup by pointer,
00468     * run the hash function. Otherwise, scan the whole container
00469     * (this only for the time being. We need to optimize this.)
00470     */
00471    if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
00472       start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
00473    else        /* don't know, let's scan all buckets */
00474       start = i = -1;      /* XXX this must be fixed later. */
00475 
00476    /* determine the search boundaries: i..last-1 */
00477    if (i < 0) {
00478       start = i = 0;
00479       last = c->n_buckets;
00480    } else if ((flags & OBJ_CONTINUE)) {
00481       last = c->n_buckets;
00482    } else {
00483       last = i + 1;
00484    }
00485 
00486    ao2_lock(c);   /* avoid modifications to the content */
00487 
00488    for (; i < last ; i++) {
00489       /* scan the list with prev-cur pointers */
00490       struct bucket_list *cur;
00491 
00492       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
00493          int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
00494 
00495          /* we found the object, performing operations according flags */
00496          if (match == 0) { /* no match, no stop, continue */
00497             continue;
00498          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
00499             i = last;
00500             break;
00501          }
00502          /* we have a match (CMP_MATCH) here */
00503          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
00504             /* it is important to handle this case before the unlink */
00505             ret = EXTERNAL_OBJ(cur->astobj);
00506             ao2_ref(ret, 1);
00507          }
00508 
00509          if (flags & OBJ_UNLINK) {  /* must unlink */
00510             struct bucket_list *x = cur;
00511 
00512             /* we are going to modify the container, so update version */
00513             ast_atomic_fetchadd_int(&c->version, 1);
00514             AST_LIST_REMOVE_CURRENT(entry);
00515             /* update number of elements and version */
00516             ast_atomic_fetchadd_int(&c->elements, -1);
00517             ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
00518             free(x); /* free the link record */
00519          }
00520 
00521          if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
00522             /* We found the only match we need */
00523             i = last;   /* force exit from outer loop */
00524             break;
00525          }
00526          if (!(flags & OBJ_NODATA)) {
00527 #if 0 /* XXX to be completed */
00528             /*
00529              * This is the multiple-return case. We need to link
00530              * the object in a list. The refcount is already increased.
00531              */
00532 #endif
00533          }
00534       }
00535       AST_LIST_TRAVERSE_SAFE_END;
00536 
00537       if (ret) {
00538          /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */
00539          break;
00540       }
00541 
00542       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
00543          /* Move to the beginning to ensure we check every bucket */
00544          i = -1;
00545          last = start;
00546       }
00547    }
00548    ao2_unlock(c);
00549    return ret;
00550 }

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

Allocate and initialize a container with the desired number of buckets.

We allocate space for a struct astobj_container, struct container and the buckets[] array.

Parameters:
n_buckets Number of buckets for hash
hash_fn Pointer to a function computing a hash value.
cmp_fn Pointer to a function comparating key-value with a string. (can be NULL)
Returns:
A pointer to a struct container.
destructor is set implicitly.

Definition at line 335 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 config_text_file_save(), create_callno_pools(), dialgroup_write(), get_lock(), init_queue(), load_module(), load_objects(), and xml_translate().

00337 {
00338    /* XXX maybe consistency check on arguments ? */
00339    /* compute the container size */
00340    size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
00341 
00342    struct ao2_container *c = ao2_alloc(container_size, container_destruct);
00343 
00344    if (!c)
00345       return NULL;
00346    
00347    c->version = 1;   /* 0 is a reserved value here */
00348    c->n_buckets = n_buckets;
00349    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00350    c->cmp_fn = cmp_fn;
00351 
00352 #ifdef AO2_DEBUG
00353    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00354 #endif
00355 
00356    return c;
00357 }

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

References ao2_container::elements.

Referenced by __queues_show(), get_unused_callno(), lock_broker(), and unload_module().

00363 {
00364    return c->elements;
00365 }

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

void ao2_iterator_destroy ( struct ao2_iterator i  ) 

struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
) [read]

void* ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 587 of file astobj2.c.

References AO2_ITERATOR_DONTLOCK, ao2_lock(), ao2_ref(), ao2_unlock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, bucket_list::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, bucket_list::version, ao2_iterator::version, and ao2_container::version.

Referenced by __iax2_show_peers(), __queues_show(), authenticate_reply(), check_access(), cli_console_active(), cli_list_devices(), compare_weight(), complete_iax2_show_peer(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), delete_profiles(), delete_routes(), destroy_pvts(), dialgroup_read(), dump_queue_members(), find_queue_by_name_rt(), 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_show_routes(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), interface_exists_global(), manager_iax2_show_peer_list(), manager_queues_status(), manager_queues_summary(), num_available_members(), poke_all_peers(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload_queues(), set_member_paused(), set_member_penalty(), stop_streams(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and update_status().

00588 {
00589    int lim;
00590    struct bucket_list *p = NULL;
00591    void *ret = NULL;
00592 
00593    if (INTERNAL_OBJ(a->c) == NULL)
00594       return NULL;
00595 
00596    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00597       ao2_lock(a->c);
00598 
00599    /* optimization. If the container is unchanged and
00600     * we have a pointer, try follow it
00601     */
00602    if (a->c->version == a->c_version && (p = a->obj) ) {
00603       if ( (p = AST_LIST_NEXT(p, entry)) )
00604          goto found;
00605       /* nope, start from the next bucket */
00606       a->bucket++;
00607       a->version = 0;
00608       a->obj = NULL;
00609    }
00610 
00611    lim = a->c->n_buckets;
00612 
00613    /* Browse the buckets array, moving to the next
00614     * buckets if we don't find the entry in the current one.
00615     * Stop when we find an element with version number greater
00616     * than the current one (we reset the version to 0 when we
00617     * switch buckets).
00618     */
00619    for (; a->bucket < lim; a->bucket++, a->version = 0) {
00620       /* scan the current bucket */
00621       AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
00622          if (p->version > a->version)
00623             goto found;
00624       }
00625    }
00626 
00627 found:
00628    if (p) {
00629       a->version = p->version;
00630       a->obj = p;
00631       a->c_version = a->c->version;
00632       ret = EXTERNAL_OBJ(p->astobj);
00633       /* inc refcount of returned object */
00634       ao2_ref(ret, 1);
00635    }
00636 
00637    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00638       ao2_unlock(a->c);
00639 
00640    return ret;
00641 }

void* ao2_link ( struct ao2_container c,
void *  newobj 
)

Add an object to a container.

Parameters:
c the container to operate on.
newobj the object to be added.
Return values:
NULL on errors
newobj on success.
This function inserts an object in a container according its key.

Note:
Remember to set the key before calling this function.

This function automatically increases the reference count to account for the reference that the container now holds to the object.

Definition at line 381 of file astobj2.c.

References ao2_lock(), ao2_ref(), ao2_unlock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_list::astobj, INTERNAL_OBJ(), OBJ_POINTER, and bucket_list::version.

Referenced by add_calltoken_ignore(), add_to_queue(), build_callno_limits(), build_device(), build_profile(), build_route(), create_callno_pools(), dialgroup_write(), find_queue_by_name_rt(), get_lock(), moh_register(), peercnt_add(), realtime_peer(), realtime_user(), reload_queues(), replace_callno(), rt_handle_member_record(), set_config(), set_fn(), store_by_peercallno(), store_by_transfercallno(), and xml_translate().

00382 {
00383    int i;
00384    /* create a new list entry */
00385    struct bucket_list *p;
00386    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00387    
00388    if (!obj)
00389       return NULL;
00390 
00391    if (INTERNAL_OBJ(c) == NULL)
00392       return NULL;
00393 
00394    p = ast_calloc(1, sizeof(*p));
00395    if (!p)
00396       return NULL;
00397 
00398    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00399 
00400    ao2_lock(c);
00401    i %= c->n_buckets;
00402    p->astobj = obj;
00403    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00404    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00405    ast_atomic_fetchadd_int(&c->elements, 1);
00406    ao2_ref(user_data, +1);
00407    ao2_unlock(c);
00408    
00409    return p;
00410 }

int ao2_lock ( void *  a  ) 

Lock an object.

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

Definition at line 130 of file astobj2.c.

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

Referenced by __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), set_member_penalty(), try_calling(), update_queue(), update_realtime_members(), and update_status().

00134 {
00135    struct astobj2 *p = INTERNAL_OBJ(user_data);
00136 
00137    if (p == NULL)
00138       return -1;
00139 
00140 #ifdef AO2_DEBUG
00141    ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00142 #endif
00143 
00144 #ifndef DEBUG_THREADS
00145    return ast_mutex_lock(&p->priv_data.lock);
00146 #else
00147    return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
00148 #endif
00149 }

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

References CMP_MATCH, and CMP_STOP.

00416 {
00417    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00418 }

int ao2_ref ( void *  o,
int  delta 
)

Reference/unreference an object and return the old refcount.

Parameters:
o A pointer to the object
delta Value to add to the reference counter.
Returns:
The value of the reference counter before the operation.
Increase/decrease the reference counter according the value of delta.

If the refcount goes to zero, the object is destroyed.

Note:
The object must not be locked by the caller of this function, as it is invalid to try to unlock it after releasing the reference.

if we know the pointer to an object, it is because we have a reference count to it, so the only case when the object can go away is when we release our reference, and it is the last one in existence.

Definition at line 200 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 __find_callno(), __queues_show(), __sip_destroy(), __unload_module(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), alloc_queue(), announce_thread(), ao2_callback(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next(), ao2_link(), ast_closestream(), ast_make_file_from_fd(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_callno_limits(), calltoken_required(), cd_cb(), compare_weight(), complete_queue_remove_member(), conf_free(), conf_run(), config_text_file_save(), copy_socket_data(), create_callno_pools(), destroy_queue(), dialgroup_read(), dialgroup_write(), dialog_ref(), dialog_unref(), dump_queue_members(), end_bridge_callback(), end_bridge_callback_data_fixup(), find_queue_by_name_rt(), free_members(), get_lock(), get_member_penalty(), get_member_status(), group_destroy(), handle_cli_iax2_show_callno_limits(), hangupcalls(), httpd_helper_thread(), iax2_destroy(), interface_exists(), interface_exists_global(), load_module(), load_objects(), manager_queues_status(), manager_queues_summary(), new_iax(), num_available_members(), parse_moved_contact(), peer_ref(), peer_unref(), peercnt_add(), peercnt_modify(), peercnt_remove_by_addr(), peercnt_remove_cb(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_ref(), queue_unref(), ref_pvt(), reload_queues(), remove_from_queue(), replace_callno(), rt_handle_member_record(), sched_delay_remove(), session_do(), set_member_paused(), set_member_penalty(), set_peercnt_limit(), set_socket_transport(), sip_destroy_peer(), sip_prepare_socket(), sip_tcp_locate(), try_calling(), unload_module(), unref_profile(), unref_pvt(), unref_route(), update_queue(), update_realtime_members(), update_status(), user_ref(), user_unref(), and xml_translate().

00201 {
00202    int current_value;
00203    int ret;
00204    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00205 
00206    if (obj == NULL)
00207       return -1;
00208 
00209    /* if delta is 0, just return the refcount */
00210    if (delta == 0)
00211       return (obj->priv_data.ref_counter);
00212 
00213    /* we modify with an atomic operation the reference counter */
00214    ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
00215    current_value = ret + delta;
00216 
00217 #ifdef AO2_DEBUG  
00218    ast_atomic_fetchadd_int(&ao2.total_refs, delta);
00219 #endif
00220 
00221    /* this case must never happen */
00222    if (current_value < 0)
00223       ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
00224 
00225    if (current_value <= 0) { /* last reference, destroy the object */
00226       if (obj->priv_data.destructor_fn != NULL) 
00227          obj->priv_data.destructor_fn(user_data);
00228 
00229       ast_mutex_destroy(&obj->priv_data.lock);
00230 #ifdef AO2_DEBUG
00231       ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
00232       ast_atomic_fetchadd_int(&ao2.total_objects, -1);
00233 #endif
00234       /* for safety, zero-out the astobj2 header and also the
00235        * first word of the user-data, which we make sure is always
00236        * allocated. */
00237       memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
00238       free(obj);
00239    }
00240 
00241    return ret;
00242 }

int ao2_trylock ( void *  a  ) 

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_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

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

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

Remove an object from the container.

  • c the container
  • obj the object to unlink
Return values:
NULL,always 
Note:
The object requested to be unlinked must be valid. However, if it turns out that it is not in the container, this function is still safe to be called.

If the object gets unlinked from the container, the container's reference to the object will be automatically released.

Definition at line 424 of file astobj2.c.

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

Referenced by build_user(), delete_profiles(), delete_routes(), destroy_pvts(), dialgroup_write(), find_queue_by_name_rt(), free_members(), get_lock(), handle_cli_iax2_prune_realtime(), leave_queue(), peercnt_remove(), prune_users(), reload_queues(), remove_by_peercallno(), remove_by_transfercallno(), remove_from_queue(), unlink_peer(), unload_module(), and update_realtime_members().

00425 {
00426    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00427       return NULL;
00428 
00429    ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
00430 
00431    return NULL;
00432 }

int ao2_unlock ( void *  a  ) 

Unlock an object.

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

Definition at line 152 of file astobj2.c.

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

Referenced by __queues_show(), add_calltoken_ignore(), add_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), build_callno_limits(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), peercnt_add(), peercnt_remove(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), remove_from_queue(), replace_callno(), ring_entry(), set_member_paused(), set_member_penalty(), try_calling(), update_queue(), update_realtime_members(), and update_status().

00156 {
00157    struct astobj2 *p = INTERNAL_OBJ(user_data);
00158 
00159    if (p == NULL)
00160       return -1;
00161 
00162 #ifdef AO2_DEBUG
00163    ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00164 #endif
00165 
00166 #ifndef DEBUG_THREADS
00167    return ast_mutex_unlock(&p->priv_data.lock);
00168 #else
00169    return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
00170 #endif
00171 }

int astobj2_init ( void   ) 

Provided by astobj2.c

Definition at line 798 of file astobj2.c.

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

00799 {
00800 #ifdef AO2_DEBUG
00801    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
00802 #endif
00803 
00804    return 0;
00805 }

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

special callback that matches all

Definition at line 437 of file astobj2.c.

References CMP_MATCH.

Referenced by ao2_callback().

00438 {
00439    return CMP_MATCH;
00440 }

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

Definition at line 646 of file astobj2.c.

References ao2_ref().

Referenced by container_destruct().

00647 {
00648    ao2_ref(obj, -1);
00649    return 0;
00650 }

static void container_destruct ( void *  c  )  [static]

Definition at line 652 of file astobj2.c.

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

Referenced by ao2_container_alloc().

00653 {
00654    struct ao2_container *c = _c;
00655    int i;
00656 
00657    ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
00658 
00659    for (i = 0; i < c->n_buckets; i++) {
00660       struct bucket_list *cur;
00661 
00662       while ((cur = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00663          ast_free(cur);
00664       }
00665    }
00666 
00667 #ifdef AO2_DEBUG
00668    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00669 #endif
00670 }

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

Referenced by ao2_container_alloc().

00327 {
00328    return 0;
00329 }

static struct astobj2* INTERNAL_OBJ ( void *  user_data  )  [static, read]

convert from a pointer _p to a user-defined object

Returns:
the pointer to the astobj2 structure

Definition at line 104 of file astobj2.c.

References AO2_MAGIC, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.

Referenced by ao2_callback(), ao2_iterator_next(), ao2_link(), ao2_lock(), ao2_ref(), ao2_trylock(), ao2_unlink(), and ao2_unlock().

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


Generated on Wed Oct 28 11:45:50 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6