diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/asterisk/astobj2.h | 68 |
1 files changed, 55 insertions, 13 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index d1fc717ad..0c780a26d 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -593,6 +593,8 @@ Operations on container include: ... do something on o ... ao2_ref(o, -1); } + + ao2_iterator_destroy(&i); \endcode The difference with the callback is that the control @@ -924,15 +926,15 @@ void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags); /*! \brief * * - * When we need to walk through a container, we use + * When we need to walk through a container, we use an * ao2_iterator to keep track of the current position. * * Because the navigation is typically done without holding the - * lock on the container across the loop, - * objects can be inserted or deleted or moved - * while we work. As a consequence, there is no guarantee that - * the we manage to touch all the elements on the list, or it - * is possible that we touch the same object multiple times. + * lock on the container across the loop, objects can be inserted or deleted + * or moved while we work. As a consequence, there is no guarantee that + * we manage to touch all the elements in the container, and it is possible + * that we touch the same object multiple times. + * * However, within the current hash table container, the following is true: * - It is not possible to miss an object in the container while iterating * unless it gets added after the iteration begins and is added to a bucket @@ -951,6 +953,10 @@ void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags); * ao2_iterator_next() has its refcount incremented, * and the reference must be explicitly released when done with it. * + * In addition, ao2_iterator_init() will hold a reference to the container + * being iterated, which will be freed when ao2_iterator_destroy() is called + * to free up the resources used by the iterator (if any). + * * Example: * * \code @@ -966,12 +972,14 @@ void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags); * ao2_ref(o, -1); * } * + * ao2_iterator_destroy(&i); + * * \endcode * */ /*! \brief - * The Astobj2 iterator + * The astobj2 iterator * * \note You are not supposed to know the internals of an iterator! * We would like the iterator to be opaque, unfortunately @@ -987,21 +995,20 @@ void *_ao2_find(struct ao2_container *c, void *arg, enum search_flags flags); * - a bucket number; * - the object_id, which is also the container version number * when the object was inserted. This identifies the object - * univoquely, however reaching the desired object requires + * uniquely, however reaching the desired object requires * scanning a list. * - a pointer, and a container version when we saved the pointer. * If the container has not changed its version number, then we * can safely follow the pointer to reach the object in constant time. * * Details are in the implementation of ao2_iterator_next() - * A freshly-initialized iterator has bucket=0, version = 0. + * A freshly-initialized iterator has bucket=0, version=0. */ struct ao2_iterator { /*! the container */ struct ao2_container *c; /*! operation flags */ int flags; -#define F_AO2I_DONTLOCK 1 /*!< don't lock when iterating */ /*! current bucket */ int bucket; /*! container version */ @@ -1012,12 +1019,47 @@ struct ao2_iterator { unsigned int version; }; -/* the flags field can contain F_AO2I_DONTLOCK, which will prevent - ao2_iterator_next calls from locking the container while it - searches for the next pointer */ +/*! Flags that can be passed to ao2_iterator_init() to modify the behavior + * of the iterator. + */ +enum ao2_iterator_flags { + /*! Prevents ao2_iterator_next() from locking the container + * while retrieving the next object from it. + */ + AO2_ITERATOR_DONTLOCK = (1 << 0), +}; +/*! + * \brief Create an iterator for a container + * + * \param c the container + * \param flags one or more flags from ao2_iterator_flags + * + * \retval the constructed iterator + * + * \note This function does \b not take a pointer to an iterator; + * rather, it returns an iterator structure that should be + * assigned to (overwriting) an existing iterator structure + * allocated on the stack or on the heap. + * + * This function will take a reference on the container being iterated. + * + */ struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags); +/*! + * \brief Destroy a container iterator + * + * \param i the iterator to destroy + * + * \retval none + * + * This function will release the container reference held by the iterator + * and any other resources it may be holding. + * + */ +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__) |