Thu Apr 28 2011 16:56:55

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
#define REF_FILE   "/tmp/refs"

Enumerations

enum  ao2_callback_type { DEFAULT, WITH_DATA }

Functions

static void * __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
static void * __ao2_callback (struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
static struct ao2_container__ao2_container_alloc (struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
static struct ao2_container__ao2_container_alloc (struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
static void * __ao2_iterator_next (struct ao2_iterator *a, struct bucket_list **q)
static struct bucket_list__ao2_link (struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
static int __ao2_ref (void *user_data, const int delta)
void * _ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn)
void * _ao2_alloc_debug (size_t data_size, ao2_destructor_fn destructor_fn, char *tag, const char *file, int line, const char *funcname, int ref_debug)
void * _ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
void * _ao2_callback_data (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data)
void * _ao2_callback_data_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag, char *file, int line, const char *funcname)
void * _ao2_callback_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
struct ao2_container_ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
struct ao2_container_ao2_container_alloc_debug (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname, int ref_debug)
void * _ao2_find (struct ao2_container *c, void *arg, enum search_flags flags)
void * _ao2_find_debug (struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
void * _ao2_iterator_next (struct ao2_iterator *a)
void * _ao2_iterator_next_debug (struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
void * _ao2_link (struct ao2_container *c, void *user_data)
void * _ao2_link_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
int _ao2_lock (void *user_data, const char *file, const char *func, int line, const char *var)
int _ao2_ref (void *user_data, const int delta)
int _ao2_ref_debug (void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
int _ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var)
void * _ao2_unlink (struct ao2_container *c, void *user_data)
void * _ao2_unlink_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
int _ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var)
void ao2_bt (void)
int ao2_container_count (struct ao2_container *c)
 Returns the number of elements in a container.
void ao2_iterator_destroy (struct ao2_iterator *i)
 Destroy a container iterator.
struct ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
 Create an iterator for 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
void * ao2_object_get_lockaddr (void *obj)
 Return the lock address of an object.
int ao2_trylock (void *user_data)
 Try locking-- (don't block if fail)
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 cb_true_data (void *user_data, void *arg, void *data, int flags)
 similar to cb_true, but is an ao2_callback_data_fn instead
static int cd_cb (void *obj, void *arg, int flag)
static int cd_cb_debug (void *obj, void *arg, int flag)
static void container_destruct (void *c)
static void container_destruct_debug (void *c)
static int hash_zero (const void *user_obj, const int flags)
 always zero hash function
static struct astobj2INTERNAL_OBJ (void *user_data)
 convert from a pointer _p to a user-defined object

Define Documentation

#define AO2_MAGIC   0xa570b123

Definition at line 51 of file astobj2.c.

Referenced by __ao2_alloc(), and INTERNAL_OBJ().

#define EXTERNAL_OBJ (   _p)    ((_p) == NULL ? NULL : (_p)->user_data)

convert from a pointer _p to an astobj2 object

Returns:
the pointer to the user-defined portion.

Definition at line 133 of file astobj2.c.

Referenced by __ao2_alloc(), __ao2_callback(), and __ao2_iterator_next().

#define REF_FILE   "/tmp/refs"

Definition at line 28 of file astobj2.c.

Referenced by _ao2_alloc_debug(), and _ao2_ref_debug().


Enumeration Type Documentation

Enumerator:
DEFAULT 
WITH_DATA 

Definition at line 123 of file astobj2.c.


Function Documentation

static void* __ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
const char *  file,
int  line,
const char *  funcname 
) [static]

Definition at line 347 of file astobj2.c.

References __ast_calloc(), 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 _ao2_alloc(), and _ao2_alloc_debug().

{
   /* allocation */
   struct astobj2 *obj;

   if (data_size < sizeof(void *))
      data_size = sizeof(void *);

#if defined(__AST_DEBUG_MALLOC)
   obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
#else
   obj = ast_calloc(1, sizeof(*obj) + data_size);
#endif

   if (obj == NULL)
      return NULL;

   ast_mutex_init(&obj->priv_data.lock);
   obj->priv_data.magic = AO2_MAGIC;
   obj->priv_data.data_size = data_size;
   obj->priv_data.ref_counter = 1;
   obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_objects, 1);
   ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
   ast_atomic_fetchadd_int(&ao2.total_refs, 1);
#endif

   /* return a pointer to the user data */
   return EXTERNAL_OBJ(obj);
}
static void * __ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
void *  cb_fn,
void *  arg,
void *  data,
enum ao2_callback_type  type,
char *  tag,
char *  file,
int  line,
const char *  funcname 
) [static]

Browse the container using different stategies accoding the flags.

Returns:
Is a pointer to an object or to a list of object if OBJ_MULTIPLE is specified. Luckily, for debug purposes, the added args (tag, file, line, funcname) aren't an excessive load to the system, as the callback should not be called as often as, say, the ao2_ref func is called.

Definition at line 645 of file astobj2.c.

References _ao2_ref(), _ao2_ref_debug(), ao2_lock(), 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(), cb_true_data(), 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, ao2_container::version, and WITH_DATA.

Referenced by _ao2_callback(), _ao2_callback_data(), _ao2_callback_data_debug(), and _ao2_callback_debug().

{
   int i, start, last;  /* search boundaries */
   void *ret = NULL;
   ao2_callback_fn *cb_default = NULL;
   ao2_callback_data_fn *cb_withdata = NULL;

   if (INTERNAL_OBJ(c) == NULL)  /* safety check on the argument */
      return NULL;

   if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
      ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
      return NULL;
   }

   /* override the match function if necessary */
   if (cb_fn == NULL) { /* if NULL, match everything */
      if (type == WITH_DATA) {
         cb_withdata = cb_true_data;
      } else {
         cb_default = cb_true;
      }
   } else {
      /* We do this here to avoid the per object casting penalty (even though
         that is probably optimized away anyway. */
      if (type == WITH_DATA) {
         cb_withdata = cb_fn;
      } else {
         cb_default = cb_fn;
      }
   }

   /*
    * XXX this can be optimized.
    * If we have a hash function and lookup by pointer,
    * run the hash function. Otherwise, scan the whole container
    * (this only for the time being. We need to optimize this.)
    */
   if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
      start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
   else        /* don't know, let's scan all buckets */
      start = i = -1;      /* XXX this must be fixed later. */

   /* determine the search boundaries: i..last-1 */
   if (i < 0) {
      start = i = 0;
      last = c->n_buckets;
   } else if ((flags & OBJ_CONTINUE)) {
      last = c->n_buckets;
   } else {
      last = i + 1;
   }

   ao2_lock(c);   /* avoid modifications to the content */

   for (; i < last ; i++) {
      /* scan the list with prev-cur pointers */
      struct bucket_list *cur;

      AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
         int match = (CMP_MATCH | CMP_STOP);

         if (type == WITH_DATA) {
            match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
         } else {
            match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
         }

         /* we found the object, performing operations according flags */
         if (match == 0) { /* no match, no stop, continue */
            continue;
         } else if (match == CMP_STOP) {  /* no match but stop, we are done */
            i = last;
            break;
         }
         /* we have a match (CMP_MATCH) here */
         if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
            /* it is important to handle this case before the unlink */
            ret = EXTERNAL_OBJ(cur->astobj);
            if (tag)
               _ao2_ref_debug(ret, 1, tag, file, line, funcname);
            else
               _ao2_ref(ret, 1);
         }

         if (flags & OBJ_UNLINK) {  /* must unlink */
            struct bucket_list *x = cur;

            /* we are going to modify the container, so update version */
            ast_atomic_fetchadd_int(&c->version, 1);
            AST_LIST_REMOVE_CURRENT(entry);
            /* update number of elements and version */
            ast_atomic_fetchadd_int(&c->elements, -1);
            if (tag)
               _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
            else
               _ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
            free(x); /* free the link record */
         }

         if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
            /* We found the only match we need */
            i = last;   /* force exit from outer loop */
            break;
         }
         if (!(flags & OBJ_NODATA)) {
#if 0 /* XXX to be completed */
            /*
             * This is the multiple-return case. We need to link
             * the object in a list. The refcount is already increased.
             */
#endif
         }
      }
      AST_LIST_TRAVERSE_SAFE_END;

      if (ret) {
         /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */
         break;
      }

      if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
         /* Move to the beginning to ensure we check every bucket */
         i = -1;
         last = start;
      }
   }
   ao2_unlock(c);
   return ret;
}
static struct ao2_container* __ao2_container_alloc ( struct ao2_container c,
const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
) [static, read]

Definition at line 467 of file astobj2.c.

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

{
   /* XXX maybe consistency check on arguments ? */
   /* compute the container size */

   if (!c)
      return NULL;
   
   c->version = 1;   /* 0 is a reserved value here */
   c->n_buckets = n_buckets;
   c->hash_fn = hash_fn ? hash_fn : hash_zero;
   c->cmp_fn = cmp_fn;

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_containers, 1);
#endif

   return c;
}
static struct ao2_container* __ao2_container_alloc ( struct ao2_container c,
const uint  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
) [static, read]
static void * __ao2_iterator_next ( struct ao2_iterator a,
struct bucket_list **  q 
) [static]

Definition at line 846 of file astobj2.c.

References AO2_ITERATOR_DONTLOCK, ao2_lock(), 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 _ao2_iterator_next(), and _ao2_iterator_next_debug().

{
   int lim;
   struct bucket_list *p = NULL;
   void *ret = NULL;

   *q = NULL;
   
   if (INTERNAL_OBJ(a->c) == NULL)
      return NULL;

   if (!(a->flags & AO2_ITERATOR_DONTLOCK))
      ao2_lock(a->c);

   /* optimization. If the container is unchanged and
    * we have a pointer, try follow it
    */
   if (a->c->version == a->c_version && (p = a->obj) ) {
      if ( (p = AST_LIST_NEXT(p, entry)) )
         goto found;
      /* nope, start from the next bucket */
      a->bucket++;
      a->version = 0;
      a->obj = NULL;
   }

   lim = a->c->n_buckets;

   /* Browse the buckets array, moving to the next
    * buckets if we don't find the entry in the current one.
    * Stop when we find an element with version number greater
    * than the current one (we reset the version to 0 when we
    * switch buckets).
    */
   for (; a->bucket < lim; a->bucket++, a->version = 0) {
      /* scan the current bucket */
      AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
         if (p->version > a->version)
            goto found;
      }
   }

found:
   if (p) {
      a->version = p->version;
      a->obj = p;
      a->c_version = a->c->version;
      ret = EXTERNAL_OBJ(p->astobj);
      /* inc refcount of returned object */
      *q = p;
   }

   return ret;
}
static struct bucket_list * __ao2_link ( struct ao2_container c,
void *  user_data,
const char *  file,
int  line,
const char *  func 
) [static, read]

Definition at line 536 of file astobj2.c.

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

Referenced by _ao2_link(), and _ao2_link_debug().

{
   int i;
   /* create a new list entry */
   struct bucket_list *p;
   struct astobj2 *obj = INTERNAL_OBJ(user_data);

   if (obj == NULL)
      return NULL;

   if (INTERNAL_OBJ(c) == NULL)
      return NULL;

   p = ast_calloc(1, sizeof(*p));
   if (!p)
      return NULL;

   i = abs(c->hash_fn(user_data, OBJ_POINTER));

   ao2_lock(c);
   i %= c->n_buckets;
   p->astobj = obj;
   p->version = ast_atomic_fetchadd_int(&c->version, 1);
   AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
   ast_atomic_fetchadd_int(&c->elements, 1);

   /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
   return p;
}
static int __ao2_ref ( void *  user_data,
const int  delta 
) [static]

Definition at line 298 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_ref(), and _ao2_ref_debug().

{
   struct astobj2 *obj = INTERNAL_OBJ(user_data);
   int current_value;
   int ret;

   if (obj == NULL)
      return -1;

   /* if delta is 0, just return the refcount */
   if (delta == 0)
      return (obj->priv_data.ref_counter);

   /* we modify with an atomic operation the reference counter */
   ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
   current_value = ret + delta;

#ifdef AO2_DEBUG  
   ast_atomic_fetchadd_int(&ao2.total_refs, delta);
#endif

   /* this case must never happen */
   if (current_value < 0)
      ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);

   if (current_value <= 0) { /* last reference, destroy the object */
      if (obj->priv_data.destructor_fn != NULL) {
         obj->priv_data.destructor_fn(user_data);
      }

      ast_mutex_destroy(&obj->priv_data.lock);
#ifdef AO2_DEBUG
      ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
      ast_atomic_fetchadd_int(&ao2.total_objects, -1);
#endif
      /* for safety, zero-out the astobj2 header and also the
       * first word of the user-data, which we make sure is always
       * allocated. */
      memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
      free(obj);
   }

   return ret;
}
void* _ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn 
)

Definition at line 401 of file astobj2.c.

References __ao2_alloc().

Referenced by _ao2_container_alloc().

{
   return __ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
}
void* _ao2_alloc_debug ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
char *  tag,
const char *  file,
int  line,
const char *  funcname,
int  ref_debug 
)

Definition at line 380 of file astobj2.c.

References __ao2_alloc(), and REF_FILE.

Referenced by _ao2_container_alloc_debug(), and _moh_class_malloc().

{
   /* allocation */
   void *obj;
   FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL;

   obj = __ao2_alloc(data_size, destructor_fn, file, line, funcname);

   if (obj == NULL)
      return NULL;
   
   if (refo) {
      fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
      fclose(refo);
   }

   /* return a pointer to the user data */
   return obj;
}
void* _ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 786 of file astobj2.c.

References __ao2_callback(), and DEFAULT.

Referenced by _ao2_find(), _ao2_unlink(), and container_destruct().

{
   return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
}
void* _ao2_callback_data ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data 
)

Definition at line 800 of file astobj2.c.

References __ao2_callback(), and WITH_DATA.

{
   return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
}
void* _ao2_callback_data_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 792 of file astobj2.c.

References __ao2_callback(), and WITH_DATA.

{
   return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
}
void* _ao2_callback_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 778 of file astobj2.c.

References __ao2_callback(), and DEFAULT.

Referenced by _ao2_find_debug(), _ao2_unlink_debug(), and container_destruct_debug().

{
   return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
}
struct ao2_container* _ao2_container_alloc ( const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
) [read]

Definition at line 501 of file astobj2.c.

References __ao2_container_alloc(), _ao2_alloc(), and container_destruct().

{
   /* XXX maybe consistency check on arguments ? */
   /* compute the container size */

   size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
   struct ao2_container *c = _ao2_alloc(container_size, container_destruct);

   return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
}
struct ao2_container* _ao2_container_alloc_debug ( const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn,
char *  tag,
char *  file,
int  line,
const char *  funcname,
int  ref_debug 
) [read]

Definition at line 488 of file astobj2.c.

References __ao2_container_alloc(), _ao2_alloc_debug(), and container_destruct_debug().

{
   /* XXX maybe consistency check on arguments ? */
   /* compute the container size */
   size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
   struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);

   return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
}
void* _ao2_find ( struct ao2_container c,
void *  arg,
enum search_flags  flags 
)

Definition at line 814 of file astobj2.c.

References _ao2_callback(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

{
   return _ao2_callback(c, flags, c->cmp_fn, arg);
}
void* _ao2_find_debug ( struct ao2_container c,
void *  arg,
enum search_flags  flags,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

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

Definition at line 809 of file astobj2.c.

References _ao2_callback_debug(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

{
   return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
}
void* _ao2_iterator_next ( struct ao2_iterator a)

Definition at line 919 of file astobj2.c.

References __ao2_iterator_next(), _ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.

{
   struct bucket_list *p = NULL;
   void *ret = NULL;

   ret = __ao2_iterator_next(a, &p);
   
   if (p) {
      /* inc refcount of returned object */
      _ao2_ref(ret, 1);
   }

   if (!(a->flags & AO2_ITERATOR_DONTLOCK))
      ao2_unlock(a->c);

   return ret;
}
void* _ao2_iterator_next_debug ( struct ao2_iterator a,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 901 of file astobj2.c.

References __ao2_iterator_next(), _ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.

{
   struct bucket_list *p;
   void *ret = NULL;

   ret = __ao2_iterator_next(a, &p);
   
   if (p) {
      /* inc refcount of returned object */
      _ao2_ref_debug(ret, 1, tag, file, line, funcname);
   }

   if (!(a->flags & AO2_ITERATOR_DONTLOCK))
      ao2_unlock(a->c);

   return ret;
}
void* _ao2_link ( struct ao2_container c,
void *  user_data 
)

Definition at line 577 of file astobj2.c.

References __ao2_link(), _ao2_ref(), and ao2_unlock().

{
   struct bucket_list *p = __ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);

   if (p) {
      _ao2_ref(user_data, +1);
      ao2_unlock(c);
   }
   return p;
}
void* _ao2_link_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 566 of file astobj2.c.

References __ao2_link(), _ao2_ref_debug(), and ao2_unlock().

{
   struct bucket_list *p = __ao2_link(c, user_data, file, line, funcname);

   if (p) {
      _ao2_ref_debug(user_data, +1, tag, file, line, funcname);
      ao2_unlock(c);
   }
   return p;
}
int _ao2_lock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 167 of file astobj2.c.

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

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);

   if (p == NULL)
      return -1;

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif

#ifndef DEBUG_THREADS
   return ast_mutex_lock(&p->priv_data.lock);
#else
   return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
#endif
}
int _ao2_ref ( void *  user_data,
const int  delta 
)

Definition at line 288 of file astobj2.c.

References __ao2_ref(), and INTERNAL_OBJ().

Referenced by __ao2_callback(), _ao2_iterator_next(), _ao2_link(), and cd_cb().

{
   struct astobj2 *obj = INTERNAL_OBJ(user_data);

   if (obj == NULL)
      return -1;

   return __ao2_ref(user_data, delta);
}
int _ao2_ref_debug ( void *  user_data,
const int  delta,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 268 of file astobj2.c.

References __ao2_ref(), __priv_data::destructor_fn, INTERNAL_OBJ(), astobj2::priv_data, __priv_data::ref_counter, and REF_FILE.

Referenced by __ao2_callback(), _ao2_iterator_next_debug(), _ao2_link_debug(), and cd_cb_debug().

{
   struct astobj2 *obj = INTERNAL_OBJ(user_data);
   
   if (obj == NULL)
      return -1;

   if (delta != 0) {
      FILE *refo = fopen(REF_FILE,"a");
      fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj->priv_data.ref_counter);
      fclose(refo);
   }
   if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
         FILE *refo = fopen(REF_FILE,"a");    
         fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);   
         fclose(refo);
   }
   return __ao2_ref(user_data, delta);
}
int _ao2_trylock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 233 of file astobj2.c.

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

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);
   int ret;
   
   if (p == NULL)
      return -1;
#ifndef DEBUG_THREADS
   ret = ast_mutex_trylock(&p->priv_data.lock);
#else
   ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
#endif

#ifdef AO2_DEBUG
   if (!ret)
      ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
   return ret;
}
void* _ao2_unlink ( struct ao2_container c,
void *  user_data 
)

Definition at line 611 of file astobj2.c.

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

{
   if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
      return NULL;

   _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);

   return NULL;
}
void* _ao2_unlink_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 600 of file astobj2.c.

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

{
   if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
      return NULL;

   _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);

   return NULL;
}
int _ao2_unlock ( void *  user_data,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Definition at line 199 of file astobj2.c.

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

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);

   if (p == NULL)
      return -1;

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_locked, -1);
#endif

#ifndef DEBUG_THREADS
   return ast_mutex_unlock(&p->priv_data.lock);
#else
   return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
#endif
}
void ao2_bt ( void  )

Definition at line 79 of file astobj2.c.

{}
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 516 of file astobj2.c.

References ao2_container::elements.

Referenced by __queues_show(), _sip_show_peers(), ast_merge_contexts_and_delete(), ast_tone_zone_count(), cli_tps_report(), do_timing(), get_unused_callno(), handle_show_hint(), handle_show_hints(), locals_show(), lock_broker(), pthread_timer_open(), and unload_module().

{
   return c->elements;
}
void ao2_iterator_destroy ( struct ao2_iterator i)

Destroy a container iterator.

destroy an iterator

Definition at line 837 of file astobj2.c.

References ao2_ref, and ao2_iterator::c.

Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_meetmelist(), alias_show(), authenticate_reply(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_list_devices(), compare_weight(), complete_core_show_hint(), complete_iax2_peers(), complete_iax2_unregister(), complete_meetmecmd(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), conf_queue_dtmf(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), 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_cli_odbc_show(), handle_feature_show(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_statechange(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_queues_status(), manager_queues_summary(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), poke_all_peers(), pp_each_user_exec(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), try_calling(), unload_module(), update_queue(), and update_realtime_members().

{
   ao2_ref(i->c, -1);
   i->c = NULL;
}
struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
) [read]

Create an iterator for a container.

initialize an iterator so we start from the first object

Definition at line 822 of file astobj2.c.

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

Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_meetmelist(), alias_show(), ast_merge_contexts_and_delete(), ast_tone_zone_iterator_init(), authenticate_reply(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_meetmecmd(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), conf_queue_dtmf(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), 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_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_statechange(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), poke_all_peers(), pp_each_user_exec(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), and update_realtime_members().

{
   struct ao2_iterator a = {
      .c = c,
      .flags = flags
   };

   ao2_ref(c, +1);
   
   return a;
}
int ao2_lock ( void *  a)

Lock an object.

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

Definition at line 153 of file astobj2.c.

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

Referenced by __ao2_callback(), __ao2_iterator_next(), __ao2_link(), __queues_show(), _sip_show_peers(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_merge(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_get_indication_tone(), ast_get_indication_zone(), ast_merge_contexts_and_delete(), ast_register_indication_country(), ast_remove_hint(), ast_set_indication_country(), ast_taskprocessor_get(), ast_taskprocessor_unreference(), ast_unregister_indication_country(), attended_abort_transfer(), bridge_channel_join(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_thread(), build_callno_limits(), build_parkinglot(), clear_stats(), compare_weight(), complete_core_show_hint(), complete_queue_remove_member(), complete_sip_user(), conf_run(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), generic_thread_loop(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), handle_show_hint(), handle_statechange(), inprocess_count(), is_our_turn(), join_conference_bridge(), join_queue(), leave_conference_bridge(), leave_queue(), load_config(), load_indications(), load_realtime_queue(), local_answer(), local_bridgedchannel(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queryoption(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_write(), locals_show(), manager_queues_status(), manager_queues_summary(), menu_callback(), moh_release(), mohalloc(), monmp3thread(), multiplexed_add_or_remove(), multiplexed_bridge_create(), multiplexed_bridge_destroy(), multiplexed_thread_function(), mwi_event_cb(), peercnt_add(), peercnt_remove(), play_prompt_to_channel(), post_join_marked(), post_join_unmarked(), pthread_timer_ack(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_open(), pthread_timer_set_rate(), 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(), reload_single_queue(), remove_from_queue(), replace_callno(), ring_entry(), run_timer(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_tcptls_write(), smart_bridge_operation(), softmix_bridge_thread(), timerfd_timer_disable_continuous(), timerfd_timer_enable_continuous(), timerfd_timer_get_event(), timerfd_timer_set_rate(), try_calling(), update_call_counter(), update_queue(), and update_realtime_members().

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);

   if (p == NULL)
      return -1;

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif

   return ast_mutex_lock(&p->priv_data.lock);
}
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 591 of file astobj2.c.

References CMP_MATCH, and CMP_STOP.

{
   return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
}
void* ao2_object_get_lockaddr ( void *  obj)

Return the lock address of an object.

Parameters:
[in]objA pointer to the object we want.
Returns:
the address of the lock, else NULL.

This function comes in handy mainly for debugging locking situations, where the locking trace code reports the lock address, this allows you to correlate against object address, to match objects to reported locks.

Since:
1.6.1

Definition at line 253 of file astobj2.c.

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

{
   struct astobj2 *p = INTERNAL_OBJ(obj);
   
   if (p == NULL)
      return NULL;

   return &p->priv_data.lock;
}
int ao2_trylock ( void *  a)

Try locking-- (don't block if fail)

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

Definition at line 217 of file astobj2.c.

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

Referenced by local_queue_frame(), and local_setoption().

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);
   int ret;
   
   if (p == NULL)
      return -1;
   ret = ast_mutex_trylock(&p->priv_data.lock);

#ifdef AO2_DEBUG
   if (!ret)
      ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
   return ret;
}
int ao2_unlock ( void *  a)

Unlock an object.

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

Definition at line 185 of file astobj2.c.

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

Referenced by __ao2_callback(), __queues_show(), _ao2_iterator_next(), _ao2_iterator_next_debug(), _ao2_link(), _ao2_link_debug(), _sip_show_peers(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_merge(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), ast_change_hint(), ast_extension_state_add(), ast_extension_state_del(), ast_get_indication_tone(), ast_get_indication_zone(), ast_merge_contexts_and_delete(), ast_register_indication_country(), ast_remove_hint(), ast_set_indication_country(), ast_taskprocessor_get(), ast_taskprocessor_unreference(), ast_unregister_indication_country(), attended_abort_transfer(), bridge_channel_join(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_thread(), build_callno_limits(), build_parkinglot(), clear_stats(), compare_weight(), complete_core_show_hint(), complete_queue_remove_member(), complete_sip_user(), conf_run(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), generic_thread_loop(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), handle_show_hint(), handle_statechange(), inprocess_count(), is_our_turn(), join_conference_bridge(), join_queue(), leave_conference_bridge(), leave_queue(), load_config(), load_indications(), load_realtime_queue(), local_answer(), local_bridgedchannel(), local_call(), local_digit_begin(), local_digit_end(), local_fixup(), local_hangup(), local_indicate(), local_queryoption(), local_queue_frame(), local_sendhtml(), local_sendtext(), local_setoption(), local_write(), locals_show(), manager_queues_status(), manager_queues_summary(), menu_callback(), moh_release(), mohalloc(), monmp3thread(), multiplexed_add_or_remove(), multiplexed_bridge_create(), multiplexed_bridge_destroy(), multiplexed_thread_function(), mwi_event_cb(), peercnt_add(), peercnt_remove(), play_prompt_to_channel(), post_join_marked(), post_join_unmarked(), pthread_timer_ack(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_open(), pthread_timer_set_rate(), 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(), reload_single_queue(), remove_from_queue(), replace_callno(), ring_entry(), run_timer(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_tcptls_write(), smart_bridge_operation(), softmix_bridge_thread(), timerfd_timer_disable_continuous(), timerfd_timer_enable_continuous(), timerfd_timer_get_event(), timerfd_timer_set_rate(), try_calling(), update_call_counter(), update_queue(), and update_realtime_members().

{
   struct astobj2 *p = INTERNAL_OBJ(user_data);

   if (p == NULL)
      return -1;

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_locked, -1);
#endif

   return ast_mutex_unlock(&p->priv_data.lock);
}
int astobj2_init ( void  )

Provided by astobj2.c

Definition at line 1125 of file astobj2.c.

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

{
#ifdef AO2_DEBUG
   ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
#endif

   return 0;
}
static int cb_true ( void *  user_data,
void *  arg,
int  flags 
) [static]

special callback that matches all

Definition at line 624 of file astobj2.c.

References CMP_MATCH.

Referenced by __ao2_callback().

{
   return CMP_MATCH;
}
static int cb_true_data ( void *  user_data,
void *  arg,
void *  data,
int  flags 
) [static]

similar to cb_true, but is an ao2_callback_data_fn instead

Definition at line 632 of file astobj2.c.

References CMP_MATCH.

Referenced by __ao2_callback().

{
   return CMP_MATCH;
}
static int cd_cb ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 940 of file astobj2.c.

References _ao2_ref().

Referenced by container_destruct().

{
   _ao2_ref(obj, -1);
   return 0;
}
static int cd_cb_debug ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 946 of file astobj2.c.

References _ao2_ref_debug().

Referenced by container_destruct_debug().

{
   _ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
   return 0;
}
static void container_destruct ( void *  c) [static]

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

{
   struct ao2_container *c = _c;
   int i;

   _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);

   for (i = 0; i < c->n_buckets; i++) {
      struct bucket_list *current;

      while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
         ast_free(current);
      }
   }

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_containers, -1);
#endif
}
static void container_destruct_debug ( void *  c) [static]

Definition at line 972 of file astobj2.c.

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

Referenced by _ao2_container_alloc_debug().

{
   struct ao2_container *c = _c;
   int i;

   _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);

   for (i = 0; i < c->n_buckets; i++) {
      struct bucket_list *current;

      while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
         ast_free(current);
      }
   }

#ifdef AO2_DEBUG
   ast_atomic_fetchadd_int(&ao2.total_containers, -1);
#endif
}
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 459 of file astobj2.c.

Referenced by __ao2_container_alloc().

{
   return 0;
}
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 105 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_ref(), _ao2_lock(), _ao2_ref(), _ao2_ref_debug(), _ao2_trylock(), _ao2_unlink(), _ao2_unlink_debug(), _ao2_unlock(), ao2_lock(), ao2_object_get_lockaddr(), ao2_trylock(), and ao2_unlock().

{
   struct astobj2 *p;

   if (!user_data) {
      ast_log(LOG_ERROR, "user_data is NULL\n");
      return NULL;
   }

   p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
   if (AO2_MAGIC != (p->priv_data.magic) ) {
      ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p);
      p = NULL;
   }

   return p;
}