📄 astobj2.h
字号:
/*! \brief * Type of a generic callback function * \param obj pointer to the (user-defined part) of an object. * \param arg callback argument from ao2_callback() * \param 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, */typedef int (ao2_callback_fn)(void *obj, void *arg, int flags);/*! \brief a very common callback is one that matches by address. */ao2_callback_fn ao2_match_by_addr;/*! \brief * A callback function will return a combination of CMP_MATCH and CMP_STOP. * The latter will terminate the search in a container. */enum _cb_results { CMP_MATCH = 0x1, /*!< the object matches the request */ CMP_STOP = 0x2, /*!< stop the search now */};/*! \brief * Flags passed to ao2_callback() and ao2_hash_fn() to modify its behaviour. */enum search_flags { /*! Unlink the object for which the callback function * returned CMP_MATCH . This is the only way to extract * objects from a container. */ OBJ_UNLINK = (1 << 0), /*! On match, don't return the object hence do not increase * its refcount. */ OBJ_NODATA = (1 << 1), /*! Don't stop at the first match in ao2_callback() * \note This is not fully implemented. */ OBJ_MULTIPLE = (1 << 2), /*! 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). */ OBJ_POINTER = (1 << 3),};/*! * 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(). */typedef int (ao2_hash_fn)(const void *obj, const int flags);/*! \name Object Containers * Here start declarations of containers. *//*@{ */struct ao2_container;/*! \brief * 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. * * \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 function comparating key-value * with a string. (can be NULL) * \return A pointer to a struct container. * * destructor is set implicitly. */struct ao2_container *ao2_container_alloc(const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn);/*! \brief * Returns the number of elements in a container. */int ao2_container_count(struct ao2_container *c);/*@} *//*! \name Object Management * Here we have functions to manage objects. * * We can use the functions below on any kind of * object defined by the user. *//*@{ *//*! * \brief Add an object to a container. * * \param c the container to operate on. * \param newobj the object to be added. * * \retval NULL on errors * \retval newobj on success. * * This function inserts an object in a container according its key. * * \note Remember to set the key before calling this function. * * \note This function automatically increases the reference count to account * for the reference that the container now holds to the object. */void *ao2_link(struct ao2_container *c, void *newobj);/*! * \brief Remove an object from the container * * \arg c the container * \arg obj the object to unlink * * \retval 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. * * \note If the object gets unlinked from the container, the container's * reference to the object will be automatically released. */void *ao2_unlink(struct ao2_container *c, void *obj);/*! \brief Used as return value if the flag OBJ_MULTIPLE is set */struct ao2_list { struct ao2_list *next; void *obj; /* pointer to the user portion of the object */};/*@} *//*! \brief * ao2_callback() is a generic function that applies cb_fn() to all objects * in a container, as described below. * * \param c A pointer to the container to operate on. * \param arg passed to the callback. * \param flags A set of flags specifying the operation to perform, partially used by the container code, but also passed to the callback. * \return A pointer to the object found/marked, * a pointer to a list of objects matching comparison function, * NULL if not found. * * If the function returns any objects, their refcount is incremented, * and the caller is in charge of decrementing them once done. * Also, in case of multiple values returned, the list used * to store the objects must be freed by the caller. * * Typically, ao2_callback() is used for two purposes: * - to perform some action (including removal from the container) on one * or more objects; in this case, cb_fn() can modify the object itself, * and to perform deletion should set CMP_MATCH on the matching objects, * and have OBJ_UNLINK set in flags. * - to look for a specific object in a container; in this case, cb_fn() * 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 * The comparison is done calling the compare function set implicitly. * The p pointer can be a pointer to an object or to a key, * we can say this looking at flags value. * If p points to an object we will search for the object pointed * by this value, otherwise we serch for a key value. * If the key is not uniq we only find the first matching valued. * If we use the OBJ_MARK flags, we mark all the objects matching * the condition. * * 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 for _find() is no. * to a key (not yet supported) * OBJ_POINTER the pointer is an object pointer * * In case we return a list, the callee must take care to destroy * that list when no longer used. * * \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. */void *ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg);/*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg) * XXX possibly change order of arguments ? */void *ao2_find(struct ao2_container *c, void *arg, enum search_flags flags);/*! \brief * * * When we need to walk through a container, we use * 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. * 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 * that is before the one the current object is in. In this case, even if * you locked the container around the entire iteration loop, you still would * not see this object, because it would still be waiting on the container * lock so that it can be added. * - It would be extremely rare to see an object twice. The only way this can * happen is if an object got unlinked from the container and added again * during the same iteration. Furthermore, when the object gets added back, * it has to be in the current or later bucket for it to be seen again. * * An iterator must be first initialized with ao2_iterator_init(), * then we can use o = ao2_iterator_next() to move from one * element to the next. Remember that the object returned by * ao2_iterator_next() has its refcount incremented, * and the reference must be explicitly released when done with it. * * Example: * * \code * * struct ao2_container *c = ... // the container we want to iterate on * struct ao2_iterator i; * struct my_obj *o; * * i = ao2_iterator_init(c, flags); * * while ( (o = ao2_iterator_next(&i)) ) { * ... do something on o ... * ao2_ref(o, -1); * } * * \endcode * *//*! \brief * The Astobj2 iterator * * \note You are not supposed to know the internals of an iterator! * We would like the iterator to be opaque, unfortunately * its size needs to be known if we want to store it around * without too much trouble. * Anyways... * The iterator has a pointer to the container, and a flags * field specifying various things e.g. whether the container * should be locked or not while navigating on it. * The iterator "points" to the current object, which is identified * by three values: * * - 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 * 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. */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 */ unsigned int c_version; /*! pointer to the current object */ void *obj; /*! container version when the object was created */ unsigned int version;};struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags);void *ao2_iterator_next(struct ao2_iterator *a);/* extra functions */void ao2_bt(void); /* backtrace */#endif /* _ASTERISK_ASTOBJ2_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -