Thu Jul 9 13:40:52 2009

Asterisk developer's documentation


astobj2.h File Reference

#include "asterisk/compat.h"

Go to the source code of this file.

Data Structures

struct  ao2_iterator
 When we need to walk through a container, we use ao2_iterator to keep track of the current position. The Astobj2 iterator. More...
struct  ao2_list
 Used as return value if the flag OBJ_MULTIPLE is set. More...

Object Containers

Here start declarations of containers.

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.

Object Management

Here we have functions to manage objects.

We can use the functions below on any kind of object defined by the user.

void * ao2_link (struct ao2_container *c, void *newobj)
 Add an object to a container.
void * ao2_unlink (struct ao2_container *c, void *obj)
 Remove an object from the container.

Defines

#define F_AO2I_DONTLOCK   1

Typedefs

typedef int( ao2_callback_fn )(void *obj, void *arg, int flags)
 Type of a generic callback function.
typedef void(*) ao2_destructor_fn (void *)
 Typedef for an object destructor. This is called just before freeing the memory for the object. It is passed a pointer to the user-defined data of the object.
typedef int( ao2_hash_fn )(const void *obj, const int flags)

Enumerations

enum  _cb_results { CMP_MATCH = 0x1, CMP_STOP = 0x2 }
 A callback function will return a combination of CMP_MATCH and CMP_STOP. The latter will terminate the search in a container. More...
enum  search_flags { OBJ_UNLINK = (1 << 0), OBJ_NODATA = (1 << 1), OBJ_MULTIPLE = (1 << 2), OBJ_POINTER = (1 << 3) }
 Flags passed to ao2_callback() and ao2_hash_fn() to modify its behaviour. More...

Functions

void * ao2_alloc (const 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, 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.
void * ao2_find (struct ao2_container *c, void *arg, enum search_flags flags)
ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
void * ao2_iterator_next (struct ao2_iterator *a)
int ao2_lock (void *a)
 Lock an object.
int ao2_ref (void *o, int delta)
 Reference/unreference an object and return the old refcount.
int ao2_trylock (void *a)
 Try locking-- (don't block if fail).
int ao2_unlock (void *a)
 Unlock an object.

Variables

ao2_callback_fn ao2_match_by_addr
 a very common callback is one that matches by address.


Detailed Description

Object Model implementing objects and containers.

Definition in file astobj2.h.


Define Documentation

#define F_AO2I_DONTLOCK   1

don't lock when iterating

Definition at line 576 of file astobj2.h.

Referenced by __queues_show(), ao2_iterator_next(), interface_exists_global(), and reload_queues().


Typedef Documentation

typedef int( ao2_callback_fn)(void *obj, void *arg, int flags)

Type of a generic callback function.

Parameters:
obj pointer to the (user-defined part) of an object.
arg callback argument from ao2_callback()
flags flags from ao2_callback()
The return values are a combination of enum _cb_results. Callback functions are used to search or manipulate objects in a container,

Definition at line 308 of file astobj2.h.

typedef void(*) ao2_destructor_fn(void *)

Typedef for an object destructor. This is called just before freeing the memory for the object. It is passed a pointer to the user-defined data of the object.

Definition at line 147 of file astobj2.h.

typedef int( ao2_hash_fn)(const void *obj, const int flags)

Type of a generic function to generate a hash value from an object. flags is ignored at the moment. Eventually, it will include the value of OBJ_POINTER passed to ao2_callback().

Definition at line 348 of file astobj2.h.


Enumeration Type Documentation

enum _cb_results

A callback function will return a combination of CMP_MATCH and CMP_STOP. The latter will terminate the search in a container.

Enumerator:
CMP_MATCH  the object matches the request
CMP_STOP  stop the search now

Definition at line 317 of file astobj2.h.

00317                  {
00318    CMP_MATCH   = 0x1,   /*!< the object matches the request */
00319    CMP_STOP = 0x2,   /*!< stop the search now */
00320 };

enum search_flags

Flags passed to ao2_callback() and ao2_hash_fn() to modify its behaviour.

Enumerator:
OBJ_UNLINK  Unlink the object for which the callback function returned CMP_MATCH . This is the only way to extract objects from a container.
OBJ_NODATA  On match, don't return the object hence do not increase its refcount.
OBJ_MULTIPLE  Don't stop at the first match in ao2_callback()
Note:
This is not fully implemented.
OBJ_POINTER  obj is an object of the same type as the one being searched for, so use the object's hash function for optimized searching. The search function is unaffected (i.e. use the one passed as argument, or match_by_addr if none specified).

Definition at line 325 of file astobj2.h.

00325                   {
00326    /*! Unlink the object for which the callback function
00327     *  returned CMP_MATCH . This is the only way to extract
00328     *  objects from a container. */
00329    OBJ_UNLINK   = (1 << 0),
00330    /*! On match, don't return the object hence do not increase
00331     *  its refcount. */
00332    OBJ_NODATA   = (1 << 1),
00333    /*! Don't stop at the first match in ao2_callback()
00334     *  \note This is not fully implemented. */
00335    OBJ_MULTIPLE = (1 << 2),
00336    /*! obj is an object of the same type as the one being searched for,
00337     *  so use the object's hash function for optimized searching.
00338     *  The search function is unaffected (i.e. use the one passed as
00339     *  argument, or match_by_addr if none specified). */
00340    OBJ_POINTER  = (1 << 3),
00341 };


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

Referenced by alloc_queue(), ao2_container_alloc(), ast_tcptls_client_start(), ast_tcptls_server_root(), build_device(), build_peer(), build_profile(), build_route(), build_user(), conf_run(), create_queue_member(), dialgroup_write(), get_filestream(), moh_class_malloc(), new_iax(), set_fn(), 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 82 of file astobj2.c.

References ast_verbose(), free, and N1.

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

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_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, and ao2_container::version.

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

00450 {
00451    int i, 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       i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
00473    else        /* don't know, let's scan all buckets */
00474       i = -1;     /* XXX this must be fixed later. */
00475 
00476    /* determine the search boundaries: i..last-1 */
00477    if (i < 0) {
00478       i = 0;
00479       last = c->n_buckets;
00480    } else {
00481       last = i + 1;
00482    }
00483 
00484    ao2_lock(c);   /* avoid modifications to the content */
00485 
00486    for (; i < last ; i++) {
00487       /* scan the list with prev-cur pointers */
00488       struct bucket_list *cur;
00489 
00490       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
00491          int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
00492 
00493          /* we found the object, performing operations according flags */
00494          if (match == 0) { /* no match, no stop, continue */
00495             continue;
00496          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
00497             i = last;
00498             break;
00499          }
00500          /* we have a match (CMP_MATCH) here */
00501          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
00502             /* it is important to handle this case before the unlink */
00503             ret = EXTERNAL_OBJ(cur->astobj);
00504             ao2_ref(ret, 1);
00505          }
00506 
00507          if (flags & OBJ_UNLINK) {  /* must unlink */
00508             struct bucket_list *x = cur;
00509 
00510             /* we are going to modify the container, so update version */
00511             ast_atomic_fetchadd_int(&c->version, 1);
00512             AST_LIST_REMOVE_CURRENT(entry);
00513             /* update number of elements and version */
00514             ast_atomic_fetchadd_int(&c->elements, -1);
00515             ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
00516             free(x); /* free the link record */
00517          }
00518 
00519          if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
00520             /* We found the only match we need */
00521             i = last;   /* force exit from outer loop */
00522             break;
00523          }
00524          if (!(flags & OBJ_NODATA)) {
00525 #if 0 /* XXX to be completed */
00526             /*
00527              * This is the multiple-return case. We need to link
00528              * the object in a list. The refcount is already increased.
00529              */
00530 #endif
00531          }
00532       }
00533       AST_LIST_TRAVERSE_SAFE_END;
00534    }
00535    ao2_unlock(c);
00536    return ret;
00537 }

struct ao2_container* ao2_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.

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(), dialgroup_write(), init_queue(), load_module(), 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().

00363 {
00364    return c->elements;
00365 }

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

References ao2_callback(), and ao2_container::cmp_fn.

Referenced by __find_callno(), authenticate_request(), authenticate_verify(), build_peer(), build_user(), compare_weight(), dialgroup_read(), dialgroup_write(), find_peer(), find_profile(), find_pvt(), find_queue_by_name_rt(), find_user(), get_member_penalty(), get_mohbyname(), handle_cli_iax2_unregister(), iax2_destroy_helper(), load_realtime_queue(), phoneprov_callback(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), reload_queue_members(), reload_queues(), remove_from_queue(), rt_handle_member_record(), set_fn(), update_queue(), and xml_translate().

00543 {
00544    return ao2_callback(c, flags, c->cmp_fn, arg);
00545 }

struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
)

initialize an iterator so we start from the first object

Definition at line 550 of file astobj2.c.

References ao2_iterator::c, and ao2_iterator::flags.

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(), free_members(), get_member_status(), 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().

00551 {
00552    struct ao2_iterator a = {
00553       .c = c,
00554       .flags = flags
00555    };
00556    
00557    return a;
00558 }

void* ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 563 of file astobj2.c.

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

00564 {
00565    int lim;
00566    struct bucket_list *p = NULL;
00567    void *ret = NULL;
00568 
00569    if (INTERNAL_OBJ(a->c) == NULL)
00570       return NULL;
00571 
00572    if (!(a->flags & F_AO2I_DONTLOCK))
00573       ao2_lock(a->c);
00574 
00575    /* optimization. If the container is unchanged and
00576     * we have a pointer, try follow it
00577     */
00578    if (a->c->version == a->c_version && (p = a->obj) ) {
00579       if ( (p = AST_LIST_NEXT(p, entry)) )
00580          goto found;
00581       /* nope, start from the next bucket */
00582       a->bucket++;
00583       a->version = 0;
00584       a->obj = NULL;
00585    }
00586 
00587    lim = a->c->n_buckets;
00588 
00589    /* Browse the buckets array, moving to the next
00590     * buckets if we don't find the entry in the current one.
00591     * Stop when we find an element with version number greater
00592     * than the current one (we reset the version to 0 when we
00593     * switch buckets).
00594     */
00595    for (; a->bucket < lim; a->bucket++, a->version = 0) {
00596       /* scan the current bucket */
00597       AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
00598          if (p->version > a->version)
00599             goto found;
00600       }
00601    }
00602 
00603 found:
00604    if (p) {
00605       a->version = p->version;
00606       a->obj = p;
00607       a->c_version = a->c->version;
00608       ret = EXTERNAL_OBJ(p->astobj);
00609       /* inc refcount of returned object */
00610       ao2_ref(ret, 1);
00611    }
00612 
00613    if (!(a->flags & F_AO2I_DONTLOCK))
00614       ao2_unlock(a->c);
00615 
00616    return ret;
00617 }

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::entry, INTERNAL_OBJ(), and OBJ_POINTER.

Referenced by add_to_queue(), build_device(), build_route(), dialgroup_write(), moh_register(), reload_queues(), 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 = 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_to_queue(), ao2_callback(), ao2_iterator_next(), ao2_link(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), 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(), 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_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(), __unload_module(), add_to_queue(), alloc_queue(), announce_thread(), ao2_callback(), ao2_link(), ast_closestream(), ast_filestream_frame_freed(), ast_make_file_from_fd(), ast_readaudio_callback(), ast_readframe(), ast_readvideo_callback(), ast_tcptls_client_start(), ast_tcptls_server_root(), cd_cb(), compare_weight(), complete_queue_remove_member(), conf_free(), conf_run(), config_text_file_save(), copy_socket_data(), destroy_queue(), dialgroup_read(), dialgroup_write(), dump_queue_members(), end_bridge_callback(), end_bridge_callback_data_fixup(), free_members(), get_member_penalty(), get_member_status(), group_destroy(), hangupcalls(), httpd_helper_thread(), iax2_destroy(), interface_exists(), interface_exists_global(), load_module(), manager_queues_status(), manager_queues_summary(), new_iax(), num_available_members(), parse_moved_contact(), peer_ref(), peer_unref(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_ref(), queue_unref(), ref_pvt(), reload_queues(), remove_from_queue(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), 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.

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(), handle_cli_iax2_prune_realtime(), leave_queue(), 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_to_queue(), ao2_callback(), ao2_link(), compare_weight(), complete_queue_remove_member(), end_bridge_callback(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), 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(), 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 }


Variable Documentation

ao2_callback_fn ao2_match_by_addr

a very common callback is one that matches by address.

Definition at line 311 of file astobj2.h.

Referenced by ao2_unlink().


Generated on Thu Jul 9 13:40:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7