astobj2.h documentation updates.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@356734 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/11.2
Richard Mudgett 13 years ago
parent ebe2c33b72
commit e43d123f11

@ -209,33 +209,37 @@ were called to appear in /tmp/refs, you can do this sort of thing:
#define dialog_unref(arg1,arg2) dialog_unref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
static struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
{
if (p)
if (p) {
ao2_ref_debug(p, 1, tag, file, line, func);
else
} else {
ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
}
return p;
}
static struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
{
if (p)
if (p) {
ao2_ref_debug(p, -1, tag, file, line, func);
}
return NULL;
}
#else
static struct sip_pvt *dialog_ref(struct sip_pvt *p, const char *tag)
{
if (p)
if (p) {
ao2_ref(p, 1);
else
} else {
ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
}
return p;
}
static struct sip_pvt *dialog_unref(struct sip_pvt *p, const char *tag)
{
if (p)
if (p) {
ao2_ref(p, -1);
}
return NULL;
}
#endif
@ -332,19 +336,22 @@ Example:
*//* Unlink us from the owner (channel) if we have one *//*
if (dialog->owner) {
if (lockowner)
if (lockowner) {
ast_channel_lock(dialog->owner);
}
ast_debug(1, "Detaching from channel %s\n", dialog->owner->name);
dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all");
if (lockowner)
if (lockowner) {
ast_channel_unlock(dialog->owner);
}
}
if (dialog->registry) {
if (dialog->registry->call == dialog)
if (dialog->registry->call == dialog) {
dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all");
}
dialog->registry = registry_unref(dialog->registry, "delete dialog->registry");
}
...
...
dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time");
In the above code, the ao2_t_unlink could end up destroying the dialog
@ -384,14 +391,15 @@ murf
typedef void (*ao2_destructor_fn)(void *);
/*! \brief
* Allocate and initialize an object.
/*!
* \brief Allocate and initialize an object.
*
* \param data_size The sizeof() of the user-defined structure.
* \param destructor_fn The destructor function (can be NULL)
* \param debug_msg
* \param debug_msg Ao2 object debug tracing message.
* \return A pointer to user-data.
*
* \details
* Allocates a struct astobj2 with sufficient space for the
* user-defined structure.
* \note
@ -405,24 +413,30 @@ typedef void (*ao2_destructor_fn)(void *);
#if defined(REF_DEBUG)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_alloc(data_size, destructor_fn) __ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
__ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_alloc(data_size, destructor_fn) \
__ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#elif defined(__AST_DEBUG_MALLOC)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_alloc(data_size, destructor_fn) __ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
__ao2_alloc_debug((data_size), (destructor_fn), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_alloc(data_size, destructor_fn) \
__ao2_alloc_debug((data_size), (destructor_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#else
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) __ao2_alloc((data_size), (destructor_fn))
#define ao2_alloc(data_size, destructor_fn) __ao2_alloc((data_size), (destructor_fn))
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
__ao2_alloc((data_size), (destructor_fn))
#define ao2_alloc(data_size, destructor_fn) \
__ao2_alloc((data_size), (destructor_fn))
#endif
void *__ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, const char *tag,
const char *file, int line, const char *funcname, int ref_debug);
void *__ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);
void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, const char *tag,
const char *file, int line, const char *funcname, int ref_debug);
void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn);
/*! @} */
@ -495,10 +509,10 @@ int __ao2_trylock(void *a, const char *file, const char *func, int line, const c
#define ao2_trylock(a) __ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)
/*!
* \brief Return the lock address of an object
* \brief Return the mutex lock address of an object
*
* \param[in] obj A pointer to the object we want.
* \return the address of the lock, else NULL.
* \return the address of the mutex lock, else NULL.
*
* This function comes in handy mainly for debugging locking
* situations, where the locking trace code reports the
@ -518,13 +532,13 @@ Internally, objects are stored in lists, hash tables or other
data structures depending on the needs.
\note NOTA BENE: at the moment the only container we support is the
hash table and its degenerate form, the list.
hash table and its degenerate form, the list.
Operations on container include:
- c = \b ao2_container_alloc(size, hash_fn, cmp_fn)
allocate a container with desired size and default compare
and hash function
allocate a container with desired size and default compare
and hash function
-The compare function returns an int, which
can be 0 for not found, CMP_STOP to stop end a traversal,
or CMP_MATCH if they are equal
@ -532,27 +546,31 @@ Operations on container include:
takes two argument, the object pointer and a flags field,
- \b ao2_find(c, arg, flags)
returns zero or more element matching a given criteria
(specified as arg). 'c' is the container pointer. Flags
returns zero or more elements matching a given criteria
(specified as arg). 'c' is the container pointer. Flags
can be:
OBJ_UNLINK - to remove the object, once found, from the container.
OBJ_NODATA - don't return the object if found (no ref count change)
OBJ_MULTIPLE - don't stop at first match
OBJ_POINTER - if set, 'arg' is an object pointer, and a hash table
OBJ_UNLINK - to remove the object, once found, from the container.
OBJ_NODATA - don't return the object if found (no ref count change)
OBJ_MULTIPLE - don't stop at first match
OBJ_POINTER - if set, 'arg' is an object pointer, and a hash table
search will be done. If not, a traversal is done.
OBJ_KEY - if set, 'arg', is a hashable item that is not an object.
Similar to OBJ_POINTER and mutually exclusive.
- \b ao2_callback(c, flags, fn, arg)
apply fn(obj, arg) to all objects in the container.
Similar to find. fn() can tell when to stop, and
do anything with the object including unlinking it.
- c is the container;
apply fn(obj, arg) to all objects in the container.
Similar to find. fn() can tell when to stop, and
do anything with the object including unlinking it.
- c is the container;
- flags can be
OBJ_UNLINK - to remove the object, once found, from the container.
OBJ_NODATA - don't return the object if found (no ref count change)
OBJ_MULTIPLE - don't stop at first match
OBJ_POINTER - if set, 'arg' is an object pointer, and a hash table
OBJ_UNLINK - to remove the object, once found, from the container.
OBJ_NODATA - don't return the object if found (no ref count change)
OBJ_MULTIPLE - don't stop at first match
OBJ_POINTER - if set, 'arg' is an object pointer, and a hash table
search will be done. If not, a traversal is done through
all the hash table 'buckets'..
OBJ_KEY - if set, 'arg', is a hashable item that is not an object.
Similar to OBJ_POINTER and mutually exclusive.
- fn is a func that returns int, and takes 3 args:
(void *obj, void *arg, int flags);
obj is an object
@ -563,39 +581,39 @@ Operations on container include:
CMP_STOP: stop search, no match
CMP_MATCH: This object is matched.
Note that the entire operation is run with the container
locked, so nobody else can change its content while we work on it.
However, we pay this with the fact that doing
anything blocking in the callback keeps the container
blocked.
The mechanism is very flexible because the callback function fn()
can do basically anything e.g. counting, deleting records, etc.
possibly using arg to store the results.
Note that the entire operation is run with the container
locked, so nobody else can change its content while we work on it.
However, we pay this with the fact that doing
anything blocking in the callback keeps the container
blocked.
The mechanism is very flexible because the callback function fn()
can do basically anything e.g. counting, deleting records, etc.
possibly using arg to store the results.
- \b iterate on a container
this is done with the following sequence
this is done with the following sequence
\code
struct ao2_container *c = ... // our container
struct ao2_iterator i;
void *o;
struct ao2_container *c = ... // our container
struct ao2_iterator i;
void *o;
i = ao2_iterator_init(c, flags);
i = ao2_iterator_init(c, flags);
while ((o = ao2_iterator_next(&i))) {
... do something on o ...
ao2_ref(o, -1);
}
while ((o = ao2_iterator_next(&i))) {
... do something on o ...
ao2_ref(o, -1);
}
ao2_iterator_destroy(&i);
ao2_iterator_destroy(&i);
\endcode
The difference with the callback is that the control
on how to iterate is left to us.
The difference with the callback is that the control
on how to iterate is left to us.
- \b ao2_ref(c, -1)
dropping a reference to a container destroys it, very simple!
dropping a reference to a container destroys it, very simple!
Containers are ao2 objects themselves, and this is why their
implementation is simple too.
@ -650,11 +668,11 @@ enum search_flags {
/*! Unlink the object for which the callback function
* returned CMP_MATCH.
*/
OBJ_UNLINK = (1 << 0),
OBJ_UNLINK = (1 << 0),
/*! On match, don't return the object hence do not increase
* its refcount.
*/
OBJ_NODATA = (1 << 1),
OBJ_NODATA = (1 << 1),
/*! Don't stop at the first match in ao2_callback() unless the result of
* of the callback function == (CMP_STOP | CMP_MATCH).
*/
@ -664,8 +682,8 @@ enum search_flags {
* The search function is unaffected (i.e. use the one passed as
* argument, or match_by_addr if none specified).
*/
OBJ_POINTER = (1 << 3),
/*!
OBJ_POINTER = (1 << 3),
/*!
* \brief Continue if a match is not found in the hashed out bucket
*
* This flag is to be used in combination with OBJ_POINTER. This tells
@ -673,23 +691,25 @@ enum search_flags {
* buckets if a match is not found in the starting bucket defined by
* the hash value on the argument.
*/
OBJ_CONTINUE = (1 << 4),
/*!
OBJ_CONTINUE = (1 << 4),
/*!
* \brief By using this flag, the ao2_container being searched will _NOT_
* be locked. Only use this flag if the ao2_container is being protected
* by another mechanism other that the internal ao2_lock.
*/
OBJ_NOLOCK = (1 << 5),
OBJ_NOLOCK = (1 << 5),
/*!
* \brief The data is hashable, but is not an object.
*
* \details
* This can be used when you want to be able to pass custom data
* to a hash function that is not a full object, but perhaps just
* a string.
* to the container's stored ao2_hash_fn and ao2_find
* ao2_callback_fn functions that is not a full object, but
* perhaps just a string.
*
* \note OBJ_KEY and OBJ_POINTER are mutually exclusive options.
*/
OBJ_KEY = (1 << 6),
OBJ_KEY = (1 << 6),
};
/*!
@ -705,17 +725,17 @@ typedef int (ao2_hash_fn)(const void *obj, const int flags);
/*@{ */
struct ao2_container;
/*! \brief
* Allocate and initialize a container
* with the desired number of buckets.
/*!
* \brief Allocate and initialize a hash container with the desired number of buckets.
*
* \details
* We allocate space for a struct astobj_container, struct container
* and the buckets[] array.
*
* \param arg1 Number of buckets for hash
* \param arg2 Pointer to a function computing a hash value.
* \param arg3 Pointer to a compare function used by ao2_find. (NULL to match everything)
* \param arg4 used for debugging.
* \param n_buckets Number of buckets for hash
* \param hash_fn Pointer to a function computing a hash value.
* \param cmp_fn Pointer to a compare function used by ao2_find. (NULL to match everything)
* \param tag used for debugging.
*
* \return A pointer to a struct container.
*
@ -724,27 +744,32 @@ struct ao2_container;
#if defined(REF_DEBUG)
#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_t_container_alloc(n_buckets, hash_fn, cmp_fn, tag) \
__ao2_container_alloc_debug((n_buckets), (hash_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#define ao2_container_alloc(n_buckets, hash_fn, cmp_fn) \
__ao2_container_alloc_debug((n_buckets), (hash_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
#elif defined(__AST_DEBUG_MALLOC)
#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_t_container_alloc(n_buckets, hash_fn, cmp_fn, tag) \
__ao2_container_alloc_debug((n_buckets), (hash_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#define ao2_container_alloc(n_buckets, hash_fn, cmp_fn) \
__ao2_container_alloc_debug((n_buckets), (hash_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
#else
#define ao2_t_container_alloc(arg1,arg2,arg3,arg4) __ao2_container_alloc((arg1), (arg2), (arg3))
#define ao2_container_alloc(arg1,arg2,arg3) __ao2_container_alloc((arg1), (arg2), (arg3))
#define ao2_t_container_alloc(n_buckets, hash_fn, cmp_fn, tag) \
__ao2_container_alloc((n_buckets), (hash_fn), (cmp_fn))
#define ao2_container_alloc(n_buckets, hash_fn, cmp_fn) \
__ao2_container_alloc((n_buckets), (hash_fn), (cmp_fn))
#endif
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,
const char *tag, char *file, int line, const char *funcname,
int ref_debug);
struct ao2_container *__ao2_container_alloc(unsigned int n_buckets, ao2_hash_fn *hash_fn,
ao2_callback_fn *cmp_fn);
struct ao2_container *__ao2_container_alloc_debug(unsigned int n_buckets,
ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
const char *tag, char *file, int line, const char *funcname, int ref_debug);
/*! \brief
* Returns the number of elements in a container.
@ -764,9 +789,9 @@ int ao2_container_count(struct ao2_container *c);
/*!
* \brief Add an object to a container.
*
* \param arg1 the container to operate on.
* \param arg2 the object to be added.
* \param arg3 used for debugging.
* \param container The container to operate on.
* \param obj The object to be added.
* \param tag used for debugging.
*
* \retval NULL on errors.
* \retval newobj on success.
@ -780,17 +805,19 @@ int ao2_container_count(struct ao2_container *c);
*/
#ifdef REF_DEBUG
#define ao2_t_link(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), 0, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_link(arg1, arg2) __ao2_link_debug((arg1), (arg2), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_link_nolock(arg1, arg2, arg3) __ao2_link_debug((arg1), (arg2), OBJ_NOLOCK, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_link_nolock(arg1, arg2) __ao2_link_debug((arg1), (arg2), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_link(container, obj, tag) __ao2_link_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_link(container, obj) __ao2_link_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_link_nolock(container, obj, tag) __ao2_link_debug((container), (obj), OBJ_NOLOCK, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_link_nolock(container, obj) __ao2_link_debug((container), (obj), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_link(arg1, arg2, arg3) __ao2_link((arg1), (arg2), 0)
#define ao2_link(arg1, arg2) __ao2_link((arg1), (arg2), 0)
#define ao2_t_link_nolock(arg1, arg2, arg3) __ao2_link((arg1), (arg2), OBJ_NOLOCK)
#define ao2_link_nolock(arg1, arg2) __ao2_link((arg1), (arg2), OBJ_NOLOCK)
#define ao2_t_link(container, obj, tag) __ao2_link((container), (obj), 0)
#define ao2_link(container, obj) __ao2_link((container), (obj), 0)
#define ao2_t_link_nolock(container, obj, tag) __ao2_link((container), (obj), OBJ_NOLOCK)
#define ao2_link_nolock(container, obj) __ao2_link((container), (obj), OBJ_NOLOCK)
#endif
@ -800,9 +827,9 @@ void *__ao2_link(struct ao2_container *c, void *newobj, int flags);
/*!
* \brief Remove an object from a container
*
* \param arg1 the container
* \param arg2 the object to unlink
* \param arg3 tag for debugging
* \param container The container to operate on.
* \param obj The object to unlink.
* \param tag used for debugging.
*
* \retval NULL, always
*
@ -816,17 +843,19 @@ void *__ao2_link(struct ao2_container *c, void *newobj, int flags);
*/
#ifdef REF_DEBUG
#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), 0, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_unlink(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_unlink_nolock(arg1, arg2, arg3) __ao2_unlink_debug((arg1), (arg2), OBJ_NOLOCK, (arg3), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_unlink_nolock(arg1, arg2) __ao2_unlink_debug((arg1), (arg2), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_unlink(container, obj, tag) __ao2_unlink_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_unlink(container, obj) __ao2_unlink_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_unlink_nolock(container, obj, tag) __ao2_unlink_debug((container), (obj), OBJ_NOLOCK, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_unlink_nolock(container, obj) __ao2_unlink_debug((container), (obj), OBJ_NOLOCK, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_unlink(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2), 0)
#define ao2_unlink(arg1, arg2) __ao2_unlink((arg1), (arg2), 0)
#define ao2_t_unlink_nolock(arg1, arg2, arg3) __ao2_unlink((arg1), (arg2), OBJ_NOLOCK)
#define ao2_unlink_nolock(arg1, arg2) __ao2_unlink((arg1), (arg2), OBJ_NOLOCK)
#define ao2_t_unlink(container, obj, tag) __ao2_unlink((container), (obj), 0)
#define ao2_unlink(container, obj) __ao2_unlink((container), (obj), 0)
#define ao2_t_unlink_nolock(container, obj, tag) __ao2_unlink((container), (obj), OBJ_NOLOCK)
#define ao2_unlink_nolock(container, obj) __ao2_unlink((container), (obj), OBJ_NOLOCK)
#endif
@ -842,28 +871,28 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
*
* \param c A pointer to the container to operate on.
* \param flags A set of flags specifying the operation to perform,
partially used by the container code, but also passed to
the callback.
- If OBJ_NODATA is set, ao2_callback will return NULL. No refcounts
of any of the traversed objects will be incremented.
On the converse, if it is NOT set (the default), The ref count
of each object for which CMP_MATCH was set will be incremented,
and you will have no way of knowing which those are, until
the multiple-object-return functionality is implemented.
- If OBJ_POINTER is set, the traversed items will be restricted
to the objects in the bucket that the object key hashes to.
* partially used by the container code, but also passed to
* the callback.
* - If OBJ_NODATA is set, ao2_callback will return NULL. No refcounts
* of any of the traversed objects will be incremented.
* On the converse, if it is NOT set (the default), The ref count
* of each object for which CMP_MATCH was set will be incremented,
* and you will have no way of knowing which those are, until
* the multiple-object-return functionality is implemented.
* - If OBJ_POINTER is set, the traversed items will be restricted
* to the objects in the bucket that the object key hashes to.
* \param cb_fn A function pointer, that will be called on all
objects, to see if they match. This function returns CMP_MATCH
if the object is matches the criteria; CMP_STOP if the traversal
should immediately stop, or both (via bitwise ORing), if you find a
match and want to end the traversal, and 0 if the object is not a match,
but the traversal should continue. This is the function that is applied
to each object traversed. Its arguments are:
(void *obj, void *arg, int flags), where:
obj is an object
arg is the same as arg passed into ao2_callback
flags is the same as flags passed into ao2_callback (flags are
also used by ao2_callback).
* objects, to see if they match. This function returns CMP_MATCH
* if the object is matches the criteria; CMP_STOP if the traversal
* should immediately stop, or both (via bitwise ORing), if you find a
* match and want to end the traversal, and 0 if the object is not a match,
* but the traversal should continue. This is the function that is applied
* to each object traversed. Its arguments are:
* (void *obj, void *arg, int flags), where:
* obj is an object
* arg is the same as arg passed into ao2_callback
* flags is the same as flags passed into ao2_callback (flags are
* also used by ao2_callback).
* \param arg passed to the callback.
* \param tag used for debugging.
* \return when OBJ_MULTIPLE is not included in the flags parameter,
@ -885,7 +914,7 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
* should not modify the object, but just return a combination of
* CMP_MATCH and CMP_STOP on the desired object.
* Other usages are also possible, of course.
*
* This function searches through a container and performs operations
* on objects according on flags passed.
* XXX describe better
@ -898,13 +927,14 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
*
* The use of flags argument is the follow:
*
* OBJ_UNLINK unlinks the object found
* OBJ_NODATA on match, do return an object
* Callbacks use OBJ_NODATA as a default
* functions such as find() do
* OBJ_MULTIPLE return multiple matches
* Default is no.
* OBJ_POINTER the pointer is an object pointer
* OBJ_UNLINK unlinks the object found
* OBJ_NODATA on match, do return an object
* Callbacks use OBJ_NODATA as a default
* functions such as find() do
* OBJ_MULTIPLE return multiple matches
* Default is no.
* OBJ_POINTER the pointer is an object pointer
* OBJ_KEY the pointer is to a hashable key
*
* \note When the returned object is no longer in use, ao2_ref() should
* be used to free the additional reference possibly created by this function.
@ -913,18 +943,23 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
*/
#ifdef REF_DEBUG
#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_callback(c, flags, cb_fn, arg, tag) \
__ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback(c, flags, cb_fn, arg) \
__ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_callback(c,flags,cb_fn,arg,tag) __ao2_callback((c), (flags), (cb_fn), (arg))
#define ao2_callback(c,flags,cb_fn,arg) __ao2_callback((c), (flags), (cb_fn), (arg))
#define ao2_t_callback(c, flags, cb_fn, arg, tag) \
__ao2_callback((c), (flags), (cb_fn), (arg))
#define ao2_callback(c, flags, cb_fn, arg) \
__ao2_callback((c), (flags), (cb_fn), (arg))
#endif
void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn,
void *arg, const char *tag, char *file, int line, const char *funcname);
void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
ao2_callback_fn *cb_fn, void *arg, const char *tag, char *file, int line,
const char *funcname);
void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg);
/*! @} */
@ -946,39 +981,47 @@ void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callb
*/
#ifdef REF_DEBUG
#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), (arg6), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data_debug((arg1), (arg2), (arg3), (arg4), (arg5), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
__ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback_data(container, flags, cb_fn, arg, data) \
__ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_callback_data(arg1,arg2,arg3,arg4,arg5,arg6) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
#define ao2_callback_data(arg1,arg2,arg3,arg4,arg5) __ao2_callback_data((arg1), (arg2), (arg3), (arg4), (arg5))
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
__ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
#define ao2_callback_data(container, flags, cb_fn, arg, data) \
__ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
#endif
void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag,
char *file, int line, const char *funcname);
ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, char *file,
int line, const char *funcname);
void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
ao2_callback_data_fn *cb_fn, void *arg, void *data);
ao2_callback_data_fn *cb_fn, void *arg, void *data);
/*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg)
* XXX possibly change order of arguments ?
*/
#ifdef REF_DEBUG
#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find_debug((arg1), (arg2), (arg3), (arg4), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_find(arg1,arg2,arg3) __ao2_find_debug((arg1), (arg2), (arg3), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_find(container, arg, flags, tag) \
__ao2_find_debug((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_find(container, arg, flags) \
__ao2_find_debug((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_find(arg1,arg2,arg3,arg4) __ao2_find((arg1), (arg2), (arg3))
#define ao2_find(arg1,arg2,arg3) __ao2_find((arg1), (arg2), (arg3))
#define ao2_t_find(container, arg, flags, tag) \
__ao2_find((container), (arg), (flags))
#define ao2_find(container, arg, flags) \
__ao2_find((container), (arg), (flags))
#endif
void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag,
char *file, int line, const char *funcname);
void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
const char *tag, char *file, int line, const char *funcname);
void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags);
/*! \brief
@ -1129,13 +1172,13 @@ void ao2_iterator_destroy(struct ao2_iterator *i);
#ifdef REF_DEBUG
#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next_debug((arg1), (arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_iterator_next(arg1) __ao2_iterator_next_debug((arg1), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next_debug((iter), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_iterator_next(iter) __ao2_iterator_next_debug((iter), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
#define ao2_t_iterator_next(arg1, arg2) __ao2_iterator_next((arg1))
#define ao2_iterator_next(arg1) __ao2_iterator_next((arg1))
#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next((iter))
#define ao2_iterator_next(iter) __ao2_iterator_next((iter))
#endif

@ -426,7 +426,7 @@ static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *
return c;
}
struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
struct ao2_container *__ao2_container_alloc_debug(unsigned int n_buckets, ao2_hash_fn *hash_fn,
ao2_callback_fn *cmp_fn, const char *tag, char *file, int line,
const char *funcname, int ref_debug)
{
@ -439,7 +439,7 @@ struct ao2_container *__ao2_container_alloc_debug(const unsigned int n_buckets,
return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
}
struct ao2_container *__ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn,
struct ao2_container *__ao2_container_alloc(unsigned int n_buckets, ao2_hash_fn *hash_fn,
ao2_callback_fn *cmp_fn)
{
/* XXX maybe consistency check on arguments ? */
@ -788,14 +788,14 @@ void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
}
void *__ao2_callback_data_debug(struct ao2_container *c,
const enum search_flags flags,
enum search_flags flags,
ao2_callback_data_fn *cb_fn, void *arg, void *data,
const char *tag, char *file, int line, const char *funcname)
{
return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
}
void *__ao2_callback_data(struct ao2_container *c, const enum search_flags flags,
void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
ao2_callback_data_fn *cb_fn, void *arg, void *data)
{
return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);

Loading…
Cancel
Save