📄 astobj2.h
字号:
/* * astobj2 - replacement containers for asterisk data structures. * * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */#ifndef _ASTERISK_ASTOBJ2_H#define _ASTERISK_ASTOBJ2_H#include "asterisk/compat.h"/*! \file * \ref AstObj2 * * \page AstObj2 Object Model implementing objects and containers.This module implements an abstraction for objects (with locks andreference counts), and containers for these user-defined objects,also supporting locking, reference counting and callbacks.The internal implementation of objects and containers is opaque to the user,so we can use different data structures as needs arise.\section AstObj2_UsageObjects USAGE - OBJECTSAn ao2 object is a block of memory that the user code can access,and for which the system keeps track (with a bit of help from theprogrammer) of the number of references around. When an object hasno more references (refcount == 0), it is destroyed, by firstinvoking whatever 'destructor' function the programmer specifies(it can be NULL if none is necessary), and then freeing the memory.This way objects can be shared without worrying who is in chargeof freeing them.As an additional feature, ao2 objects are associated to individuallocks.Creating an object requires the size of the object andand a pointer to the destructor function: struct foo *o; o = ao2_alloc(sizeof(struct foo), my_destructor_fn);The value returned points to the user-visible portion of the objects(user-data), but is also used as an identifier for all object-relatedoperations such as refcount and lock manipulations.On return from ao2_alloc(): - the object has a refcount = 1; - the memory for the object is allocated dynamically and zeroed; - we cannot realloc() the object itself; - we cannot call free(o) to dispose of the object. Rather, we tell the system that we do not need the reference anymore: ao2_ref(o, -1) causing the destructor to be called (and then memory freed) when the refcount goes to 0. This is also available as ao2_unref(o), and returns NULL as a convenience, so you can do things like o = ao2_unref(o); and clean the original pointer to prevent errors.- ao2_ref(o, +1) can be used to modify the refcount on the object in case we want to pass it around.- ao2_lock(obj), ao2_unlock(obj), ao2_trylock(obj) can be used to manipulate the lock associated with the object.\section AstObj2_UsageContainers USAGE - CONTAINERSAn ao2 container is an abstract data structure where we can storeao2 objects, search them (hopefully in an efficient way), and iterateor apply a callback function to them. A container is just an ao2 objectitself.A container must first be allocated, specifying the initialparameters. At the moment, this is done as follows: <b>Sample Usage:</b> \code struct ao2_container *c; c = ao2_container_alloc(MAX_BUCKETS, my_hash_fn, my_cmp_fn); \endcodewhere- MAX_BUCKETS is the number of buckets in the hash table,- my_hash_fn() is the (user-supplied) function that returns a hash key for the object (further reduced modulo MAX_BUCKETS by the container's code);- my_cmp_fn() is the default comparison function used when doing searches on the container,A container knows little or nothing about the objects it stores,other than the fact that they have been created by ao2_alloc().All knowledge of the (user-defined) internals of the objectsis left to the (user-supplied) functions passed as argumentsto ao2_container_alloc().If we want to insert an object in a container, we shouldinitialize its fields -- especially, those used by my_hash_fn() --to compute the bucket to use.Once done, we can link an object to a container with ao2_link(c, o);The function returns NULL in case of errors (and the objectis not inserted in the container). Other values mean success(we are not supposed to use the value as a pointer to anything).\note While an object o is in a container, we expect thatmy_hash_fn(o) will always return the same value. The functiondoes not lock the object to be computed, so modifications ofthose fields that affect the computation of the hash shouldbe done by extracting the object from the container, andreinserting it after the change (this is not terribly expensive).\note A container with a single buckets is effectively a linkedlist. However there is no ordering among elements.- \ref AstObj2_Containers- \ref astobj2.h All documentation for functions and data structures *//*! \brief * 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 void (*ao2_destructor_fn)(void *);/*! \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) * \return 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); */void *ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn);/*! \brief * Reference/unreference an object and return the old refcount. * * \param o A pointer to the object * \param delta Value to add to the reference counter. * \return 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. * * \note 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. */int ao2_ref(void *o, int delta);/*! \brief * Lock an object. * * \param a A pointer to the object we want lock. * \return 0 on success, other values on error. */#ifndef DEBUG_THREADSint ao2_lock(void *a);#else#define ao2_lock(a) _ao2_lock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)int _ao2_lock(void *a, const char *file, const char *func, int line, const char *var);#endif/*! \brief * Unlock an object. * * \param a A pointer to the object we want unlock. * \return 0 on success, other values on error. */#ifndef DEBUG_THREADSint ao2_unlock(void *a);#else#define ao2_unlock(a) _ao2_unlock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)int _ao2_unlock(void *a, const char *file, const char *func, int line, const char *var);#endif/*! \brief * Try locking-- (don't block if fail) * * \param a A pointer to the object we want to lock. * \return 0 on success, other values on error. */#ifndef DEBUG_THREADSint ao2_trylock(void *a);#else#define ao2_trylock(a) _ao2_trylock(a, __FILE__, __PRETTY_FUNCTION__, __LINE__, #a)int _ao2_trylock(void *a, const char *file, const char *func, int line, const char *var);#endif/*! * \page AstObj2_Containers AstObj2 ContainersContainers are data structures meant to store several objects,and perform various operations on them.Internally, objects are stored in lists, hash tables or otherdata 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.Operations on container include: - c = \b ao2_container_alloc(size, cmp_fn, hash_fn) allocate a container with desired size and default compare and hash function - \b ao2_find(c, arg, flags) returns zero or more element matching a given criteria (specified as arg). Flags indicate how many results we want (only one or all matching entries), and whether we should unlink the object from the container. - \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. Note that the entire operation is run with the container locked, so noone 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\code struct ao2_container *c = ... // our container struct ao2_iterator i; void *o; i = ao2_iterator_init(c, flags); while ( (o = ao2_iterator_next(&i)) ) { ... do something on o ... ao2_ref(o, -1); }\endcode 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! Containers are ao2 objects themselves, and this is why theirimplementation is simple too.Before declaring containers, we need to declare the types of thearguments passed to the constructor - in turn, this requiresto define callback and hash functions and their arguments.- \ref AstObj2- \ref astobj2.h */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -