123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * 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.
- */
- /*! \file
- * \brief Object Model for Asterisk
- *
- * \deprecated Use astobj2.h instead
- */
- #ifndef _ASTERISK_ASTOBJ_H
- #define _ASTERISK_ASTOBJ_H
- #include "asterisk/lock.h"
- /*! \file
- * \brief A set of macros implementing objects and containers.
- * Macros are used for maximum performance, to support multiple inheritance,
- * and to be easily integrated into existing structures without additional
- * malloc calls, etc.
- *
- * These macros expect to operate on two different object types, ASTOBJs and
- * ASTOBJ_CONTAINERs. These are not actual types, as any struct can be
- * converted into an ASTOBJ compatible object or container using the supplied
- * macros.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_object {
- * ASTOBJ_COMPONENTS(struct sample_object);
- * };
- *
- * struct sample_container {
- * ASTOBJ_CONTAINER_COMPONENTS(struct sample_object);
- * } super_container;
- *
- * void sample_object_destroy(struct sample_object *obj)
- * {
- * free(obj);
- * }
- *
- * int init_stuff()
- * {
- * struct sample_object *obj1;
- * struct sample_object *found_obj;
- *
- * obj1 = malloc(sizeof(struct sample_object));
- *
- * ASTOBJ_CONTAINER_INIT(&super_container);
- *
- * ASTOBJ_INIT(obj1);
- * ASTOBJ_WRLOCK(obj1);
- * ast_copy_string(obj1->name, "obj1", sizeof(obj1->name));
- * ASTOBJ_UNLOCK(obj1);
- *
- * ASTOBJ_CONTAINER_LINK(&super_container, obj1);
- *
- * found_obj = ASTOBJ_CONTAINER_FIND(&super_container, "obj1");
- *
- * if(found_obj) {
- * printf("Found object: %s", found_obj->name);
- * ASTOBJ_UNREF(found_obj,sample_object_destroy);
- * }
- *
- * ASTOBJ_CONTAINER_DESTROYALL(&super_container,sample_object_destroy);
- * ASTOBJ_CONTAINER_DESTROY(&super_container);
- *
- * return 0;
- * }
- * \endcode
- */
- #if defined(__cplusplus) || defined(c_plusplus)
- extern "C" {
- #endif
- #define ASTOBJ_DEFAULT_NAMELEN 80
- #define ASTOBJ_DEFAULT_BUCKETS 256
- #define ASTOBJ_DEFAULT_HASH ast_strhash
- #define ASTOBJ_FLAG_MARKED (1 << 0) /* Object has been marked for future operation */
- /* C++ is simply a syntactic crutch for those who cannot think for themselves
- in an object oriented way. */
- /*! \brief Lock an ASTOBJ for reading.
- */
- #define ASTOBJ_RDLOCK(object) ast_mutex_lock(&(object)->_lock)
- /*! \brief Lock an ASTOBJ for writing.
- */
- #define ASTOBJ_WRLOCK(object) ast_mutex_lock(&(object)->_lock)
- #define ASTOBJ_TRYWRLOCK(object) ast_mutex_trylock(&(object)->_lock)
- /*! \brief Unlock a locked object. */
- #define ASTOBJ_UNLOCK(object) ast_mutex_unlock(&(object)->_lock)
- #ifdef ASTOBJ_CONTAINER_HASHMODEL
- #define __ASTOBJ_HASH(type,hashes) \
- type *next[hashes]
- #else
- #define __ASTOBJ_HASH(type,hashes) \
- type *next[1]
- #endif
- /*! \brief Add ASTOBJ components to a struct (without locking support).
- *
- * \param type The datatype of the object.
- * \param namelen The length to make the name char array.
- * \param hashes The number of containers the object can be present in.
- *
- * This macro adds components to a struct to make it an ASTOBJ. This macro
- * differs from ASTOBJ_COMPONENTS_FULL in that it does not create a mutex for
- * locking.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct {
- * ASTOBJ_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
- * };
- * \endcode
- */
- #define ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes) \
- char name[namelen]; \
- unsigned int refcount; \
- unsigned int objflags; \
- __ASTOBJ_HASH(type,hashes)
- /*! \brief Add ASTOBJ components to a struct (without locking support).
- *
- * \param type The datatype of the object.
- *
- * This macro works like #ASTOBJ_COMPONENTS_NOLOCK_FULL() except it only accepts a
- * type and uses default values for namelen and hashes.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_componets {
- * ASTOBJ_COMPONENTS_NOLOCK(struct sample_struct);
- * };
- * \endcode
- */
- #define ASTOBJ_COMPONENTS_NOLOCK(type) \
- ASTOBJ_COMPONENTS_NOLOCK_FULL(type,ASTOBJ_DEFAULT_NAMELEN,1)
- /*! \brief Add ASTOBJ components to a struct (with locking support).
- *
- * \param type The datatype of the object.
- *
- * This macro works like #ASTOBJ_COMPONENTS_NOLOCK() except it includes locking
- * support.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct {
- * ASTOBJ_COMPONENTS(struct sample_struct);
- * };
- * \endcode
- */
- #define ASTOBJ_COMPONENTS(type) \
- ASTOBJ_COMPONENTS_NOLOCK(type); \
- ast_mutex_t _lock;
- /*! \brief Add ASTOBJ components to a struct (with locking support).
- *
- * \param type The datatype of the object.
- * \param namelen The length to make the name char array.
- * \param hashes The number of containers the object can be present in.
- *
- * This macro adds components to a struct to make it an ASTOBJ and includes
- * support for locking.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct {
- * ASTOBJ_COMPONENTS_FULL(struct sample_struct,1,1);
- * };
- * \endcode
- */
- #define ASTOBJ_COMPONENTS_FULL(type,namelen,hashes) \
- ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes); \
- ast_mutex_t _lock;
- /*! \brief Increment an object reference count.
- * \param object A pointer to the object to operate on.
- * \return The object.
- */
- #define ASTOBJ_REF(object) \
- ({ \
- ASTOBJ_WRLOCK(object); \
- (object)->refcount++; \
- ASTOBJ_UNLOCK(object); \
- (object); \
- })
- /*! \brief Decrement the reference count on an object.
- *
- * \param object A pointer the object to operate on.
- * \param destructor The destructor to call if the object is no longer referenced. It will be passed the pointer as an argument.
- *
- * This macro unreferences an object and calls the specfied destructor if the
- * object is no longer referenced. The destructor should free the object if it
- * was dynamically allocated.
- */
- #define ASTOBJ_UNREF(object,destructor) \
- do { \
- int newcount = 0; \
- ASTOBJ_WRLOCK(object); \
- if (__builtin_expect((object)->refcount > 0, 1)) \
- newcount = --((object)->refcount); \
- else \
- ast_log(AST_LOG_WARNING, "Unreferencing unreferenced (object)!\n"); \
- ASTOBJ_UNLOCK(object); \
- if (newcount == 0) { \
- ast_mutex_destroy(&(object)->_lock); \
- destructor((object)); \
- } \
- (object) = NULL; \
- } while(0)
- /*! \brief Mark an ASTOBJ by adding the #ASTOBJ_FLAG_MARKED flag to its objflags mask.
- * \param object A pointer to the object to operate on.
- *
- * This macro "marks" an object. Marked objects can later be unlinked from a container using
- * #ASTOBJ_CONTAINER_PRUNE_MARKED().
- *
- */
- #define ASTOBJ_MARK(object) \
- do { \
- ASTOBJ_WRLOCK(object); \
- (object)->objflags |= ASTOBJ_FLAG_MARKED; \
- ASTOBJ_UNLOCK(object); \
- } while(0)
- /*! \brief Unmark an ASTOBJ by subtracting the #ASTOBJ_FLAG_MARKED flag from its objflags mask.
- * \param object A pointer to the object to operate on.
- */
- #define ASTOBJ_UNMARK(object) \
- do { \
- ASTOBJ_WRLOCK(object); \
- (object)->objflags &= ~ASTOBJ_FLAG_MARKED; \
- ASTOBJ_UNLOCK(object); \
- } while(0)
- /*! \brief Initialize an object.
- * \param object A pointer to the object to operate on.
- *
- * \note This should only be used on objects that support locking (objects
- * created with #ASTOBJ_COMPONENTS() or #ASTOBJ_COMPONENTS_FULL())
- */
- #define ASTOBJ_INIT(object) \
- do { \
- ast_mutex_init(&(object)->_lock); \
- object->name[0] = '\0'; \
- object->refcount = 1; \
- } while(0)
- /* Containers for objects -- current implementation is linked lists, but
- should be able to be converted to hashes relatively easily */
- /*! \brief Lock an ASTOBJ_CONTAINER for reading.
- */
- #define ASTOBJ_CONTAINER_RDLOCK(container) ast_mutex_lock(&(container)->_lock)
- /*! \brief Lock an ASTOBJ_CONTAINER for writing.
- */
- #define ASTOBJ_CONTAINER_WRLOCK(container) ast_mutex_lock(&(container)->_lock)
- /*! \brief Unlock an ASTOBJ_CONTAINER. */
- #define ASTOBJ_CONTAINER_UNLOCK(container) ast_mutex_unlock(&(container)->_lock)
- #ifdef ASTOBJ_CONTAINER_HASHMODEL
- #error "Hash model for object containers not yet implemented!"
- #else
- /* Linked lists */
- /*! \brief Create a container for ASTOBJs (without locking support).
- *
- * \param type The type of objects the container will hold.
- * \param hashes Currently unused.
- * \param buckets Currently unused.
- *
- * This macro is used to create a container for ASTOBJs without locking
- * support.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_nolock_container {
- * ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
- * };
- * \endcode
- */
- #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,hashes,buckets) \
- type *head
- /*! \brief Initialize a container.
- *
- * \param container A pointer to the container to initialize.
- * \param hashes Currently unused.
- * \param buckets Currently unused.
- *
- * This macro initializes a container. It should only be used on containers
- * that support locking.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_container {
- * ASTOBJ_CONTAINER_COMPONENTS_FULL(struct sample_struct,1,1);
- * } container;
- *
- * int func()
- * {
- * ASTOBJ_CONTAINER_INIT_FULL(&container,1,1);
- * }
- * \endcode
- */
- #define ASTOBJ_CONTAINER_INIT_FULL(container,hashes,buckets) \
- do { \
- ast_mutex_init(&(container)->_lock); \
- } while(0)
- /*! \brief Destroy a container.
- *
- * \param container A pointer to the container to destroy.
- * \param hashes Currently unused.
- * \param buckets Currently unused.
- *
- * This macro frees up resources used by a container. It does not operate on
- * the objects in the container. To unlink the objects from the container use
- * #ASTOBJ_CONTAINER_DESTROYALL().
- *
- * \note This macro should only be used on containers with locking support.
- */
- #define ASTOBJ_CONTAINER_DESTROY_FULL(container,hashes,buckets) \
- do { \
- ast_mutex_destroy(&(container)->_lock); \
- } while(0)
- /*! \brief Iterate through the objects in a container.
- *
- * \param container A pointer to the container to traverse.
- * \param continue A condition to allow the traversal to continue.
- * \param eval A statement to evaluate in the iteration loop.
- *
- * This is macro is a little complicated, but it may help to think of it as a
- * loop. Basically it iterates through the specfied containter as long as the
- * condition is met. Two variables, iterator and next, are provided for use in
- * your \p eval statement. See the sample code for an example.
- *
- * <b>Sample Usage:</b>
- * \code
- * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, {
- * ASTOBJ_RDLOCK(iterator);
- * printf("Currently iterating over '%s'\n", iterator->name);
- * ASTOBJ_UNLOCK(iterator);
- * } );
- * \endcode
- *
- * \code
- * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, sample_func(iterator));
- * \endcode
- */
- #define ASTOBJ_CONTAINER_TRAVERSE(container,continue,eval) \
- do { \
- typeof((container)->head) iterator; \
- typeof((container)->head) next; \
- ASTOBJ_CONTAINER_RDLOCK(container); \
- next = (container)->head; \
- while((continue) && (iterator = next)) { \
- next = iterator->next[0]; \
- eval; \
- } \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } while(0)
- /*! \brief Find an object in a container.
- *
- * \param container A pointer to the container to search.
- * \param namestr The name to search for.
- *
- * Use this function to find an object with the specfied name in a container.
- *
- * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
- * be used to free the additional reference created by this macro.
- *
- * \return A new reference to the object located or NULL if nothing is found.
- */
- #define ASTOBJ_CONTAINER_FIND(container,namestr) \
- ({ \
- typeof((container)->head) found = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
- if (!(strcasecmp(iterator->name, (namestr)))) \
- found = ASTOBJ_REF(iterator); \
- } while (0)); \
- found; \
- })
- /*! \brief Find an object in a container.
- *
- * \param container A pointer to the container to search.
- * \param data The data to search for.
- * \param field The field/member of the container's objects to search.
- * \param hashfunc The hash function to use, currently not implemented.
- * \param hashoffset The hash offset to use, currently not implemented.
- * \param comparefunc The function used to compare the field and data values.
- *
- * This macro iterates through a container passing the specified field and data
- * elements to the specified comparefunc. The function should return 0 when a match is found.
- *
- * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
- * be used to free the additional reference created by this macro.
- *
- * \return A pointer to the object located or NULL if nothing is found.
- */
- #define ASTOBJ_CONTAINER_FIND_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
- ({ \
- typeof((container)->head) found = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
- ASTOBJ_RDLOCK(iterator); \
- if (!(comparefunc(iterator->field, (data)))) { \
- found = ASTOBJ_REF(iterator); \
- } \
- ASTOBJ_UNLOCK(iterator); \
- } while (0)); \
- found; \
- })
- /*! \brief Empty a container.
- *
- * \param container A pointer to the container to operate on.
- * \param destructor A destructor function to call on each object.
- *
- * This macro loops through a container removing all the items from it using
- * #ASTOBJ_UNREF(). This does not destroy the container itself, use
- * #ASTOBJ_CONTAINER_DESTROY() for that.
- *
- * \note If any object in the container is only referenced by the container,
- * the destructor will be called for that object once it has been removed.
- */
- #define ASTOBJ_CONTAINER_DESTROYALL(container,destructor) \
- do { \
- typeof((container)->head) iterator; \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- while((iterator = (container)->head)) { \
- (container)->head = (iterator)->next[0]; \
- ASTOBJ_UNREF(iterator,destructor); \
- } \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } while(0)
- /*! \brief Remove an object from a container.
- *
- * \param container A pointer to the container to operate on.
- * \param obj A pointer to the object to remove.
- *
- * This macro iterates through a container and removes the specfied object if
- * it exists in the container.
- *
- * \note This macro does not destroy any objects, it simply unlinks
- * them from the list. No destructors are called.
- *
- * \return The container's reference to the removed object or NULL if no
- * matching object was found.
- */
- #define ASTOBJ_CONTAINER_UNLINK(container,obj) \
- ({ \
- typeof((container)->head) found = NULL; \
- typeof((container)->head) prev = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
- if (iterator == obj) { \
- found = iterator; \
- found->next[0] = NULL; \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- if (prev) \
- prev->next[0] = next; \
- else \
- (container)->head = next; \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } \
- prev = iterator; \
- } while (0)); \
- found; \
- })
- /*! \brief Find and remove an object from a container.
- *
- * \param container A pointer to the container to operate on.
- * \param namestr The name of the object to remove.
- *
- * This macro iterates through a container and removes the first object with
- * the specfied name from the container.
- *
- * \note This macro does not destroy any objects, it simply unlinks
- * them. No destructors are called.
- *
- * \return The container's reference to the removed object or NULL if no
- * matching object was found.
- */
- #define ASTOBJ_CONTAINER_FIND_UNLINK(container,namestr) \
- ({ \
- typeof((container)->head) found = NULL; \
- typeof((container)->head) prev = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
- if (!(strcasecmp(iterator->name, (namestr)))) { \
- found = iterator; \
- found->next[0] = NULL; \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- if (prev) \
- prev->next[0] = next; \
- else \
- (container)->head = next; \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } \
- prev = iterator; \
- } while (0)); \
- found; \
- })
- /*! \brief Find and remove an object in a container.
- *
- * \param container A pointer to the container to search.
- * \param data The data to search for.
- * \param field The field/member of the container's objects to search.
- * \param hashfunc The hash function to use, currently not implemented.
- * \param hashoffset The hash offset to use, currently not implemented.
- * \param comparefunc The function used to compare the field and data values.
- *
- * This macro iterates through a container passing the specified field and data
- * elements to the specified comparefunc. The function should return 0 when a match is found.
- * If a match is found it is removed from the list.
- *
- * \note This macro does not destroy any objects, it simply unlinks
- * them. No destructors are called.
- *
- * \return The container's reference to the removed object or NULL if no match
- * was found.
- */
- #define ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
- ({ \
- typeof((container)->head) found = NULL; \
- typeof((container)->head) prev = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
- ASTOBJ_RDLOCK(iterator); \
- if (!(comparefunc(iterator->field, (data)))) { \
- found = iterator; \
- found->next[0] = NULL; \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- if (prev) \
- prev->next[0] = next; \
- else \
- (container)->head = next; \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } \
- ASTOBJ_UNLOCK(iterator); \
- prev = iterator; \
- } while (0)); \
- found; \
- })
- /*! \brief Add an object to the end of a container.
- *
- * \param container A pointer to the container to operate on.
- * \param newobj A pointer to the object to be added.
- *
- * This macro adds an object to the end of a container.
- */
- #define ASTOBJ_CONTAINER_LINK_END(container,newobj) \
- do { \
- typeof((container)->head) iterator; \
- typeof((container)->head) next; \
- typeof((container)->head) prev; \
- ASTOBJ_CONTAINER_RDLOCK(container); \
- prev = NULL; \
- next = (container)->head; \
- while((iterator = next)) { \
- next = iterator->next[0]; \
- prev = iterator; \
- } \
- if(prev) { \
- ASTOBJ_CONTAINER_WRLOCK((container)); \
- prev->next[0] = ASTOBJ_REF(newobj); \
- (newobj)->next[0] = NULL; \
- ASTOBJ_CONTAINER_UNLOCK((container)); \
- } else { \
- ASTOBJ_CONTAINER_LINK_START((container),(newobj)); \
- } \
- ASTOBJ_CONTAINER_UNLOCK((container)); \
- } while(0)
- /*! \brief Add an object to the front of a container.
- *
- * \param container A pointer to the container to operate on.
- * \param newobj A pointer to the object to be added.
- *
- * This macro adds an object to the start of a container.
- */
- #define ASTOBJ_CONTAINER_LINK_START(container,newobj) \
- do { \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- (newobj)->next[0] = (container)->head; \
- (container)->head = ASTOBJ_REF(newobj); \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } while(0)
- /*! \brief Remove an object from the front of a container.
- *
- * \param container A pointer to the container to operate on.
- *
- * This macro removes the first object in a container.
- *
- * \note This macro does not destroy any objects, it simply unlinks
- * them from the list. No destructors are called.
- *
- * \return The container's reference to the removed object or NULL if no
- * matching object was found.
- */
- #define ASTOBJ_CONTAINER_UNLINK_START(container) \
- ({ \
- typeof((container)->head) found = NULL; \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- if((container)->head) { \
- found = (container)->head; \
- (container)->head = (container)->head->next[0]; \
- found->next[0] = NULL; \
- } \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- found; \
- })
- /*! \brief Prune marked objects from a container.
- *
- * \param container A pointer to the container to prune.
- * \param destructor A destructor function to call on each marked object.
- *
- * This macro iterates through the specfied container and prunes any marked
- * objects executing the specfied destructor if necessary.
- */
- #define ASTOBJ_CONTAINER_PRUNE_MARKED(container,destructor) \
- do { \
- typeof((container)->head) prev = NULL; \
- ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { \
- ASTOBJ_RDLOCK(iterator); \
- if (iterator->objflags & ASTOBJ_FLAG_MARKED) { \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- if (prev) \
- prev->next[0] = next; \
- else \
- (container)->head = next; \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- ASTOBJ_UNLOCK(iterator); \
- ASTOBJ_UNREF(iterator,destructor); \
- continue; \
- } \
- ASTOBJ_UNLOCK(iterator); \
- prev = iterator; \
- } while (0)); \
- } while(0)
- /*! \brief Add an object to a container.
- *
- * \param container A pointer to the container to operate on.
- * \param newobj A pointer to the object to be added.
- * \param data Currently unused.
- * \param field Currently unused.
- * \param hashfunc Currently unused.
- * \param hashoffset Currently unused.
- * \param comparefunc Currently unused.
- *
- * Currently this function adds an object to the head of the list. One day it
- * will support adding objects atthe position specified using the various
- * options this macro offers.
- */
- #define ASTOBJ_CONTAINER_LINK_FULL(container,newobj,data,field,hashfunc,hashoffset,comparefunc) \
- do { \
- ASTOBJ_CONTAINER_WRLOCK(container); \
- (newobj)->next[0] = (container)->head; \
- (container)->head = ASTOBJ_REF(newobj); \
- ASTOBJ_CONTAINER_UNLOCK(container); \
- } while(0)
- #endif /* List model */
- /* Common to hash and linked list models */
- /*! \brief Create a container for ASTOBJs (without locking support).
- *
- * \param type The type of objects the container will hold.
- *
- * This macro is used to create a container for ASTOBJs without locking
- * support.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_nolock_container {
- * ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(struct sample_struct);
- * };
- * \endcode
- */
- #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) \
- ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,1,ASTOBJ_DEFAULT_BUCKETS)
- /*! \brief Create a container for ASTOBJs (with locking support).
- *
- * \param type The type of objects the container will hold.
- *
- * This macro is used to create a container for ASTOBJs with locking support.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_container {
- * ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
- * };
- * \endcode
- */
- #define ASTOBJ_CONTAINER_COMPONENTS(type) \
- ast_mutex_t _lock; \
- ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type)
- /*! \brief Initialize a container.
- *
- * \param container A pointer to the container to initialize.
- *
- * This macro initializes a container. It should only be used on containers
- * that support locking.
- *
- * <b>Sample Usage:</b>
- * \code
- * struct sample_struct_container {
- * ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
- * } container;
- *
- * int func()
- * {
- * ASTOBJ_CONTAINER_INIT(&container);
- * }
- * \endcode
- */
- #define ASTOBJ_CONTAINER_INIT(container) \
- ASTOBJ_CONTAINER_INIT_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
- /*! \brief Destroy a container.
- *
- * \param container A pointer to the container to destory.
- *
- * This macro frees up resources used by a container. It does not operate on
- * the objects in the container. To unlink the objects from the container use
- * #ASTOBJ_CONTAINER_DESTROYALL().
- *
- * \note This macro should only be used on containers with locking support.
- */
- #define ASTOBJ_CONTAINER_DESTROY(container) \
- ASTOBJ_CONTAINER_DESTROY_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
- /*! \brief Add an object to a container.
- *
- * \param container A pointer to the container to operate on.
- * \param newobj A pointer to the object to be added.
- *
- * Currently this macro adds an object to the head of a container. One day it
- * should add an object in alphabetical order.
- */
- #define ASTOBJ_CONTAINER_LINK(container,newobj) \
- ASTOBJ_CONTAINER_LINK_FULL(container,newobj,(newobj)->name,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
- /*! \brief Mark all the objects in a container.
- * \param container A pointer to the container to operate on.
- */
- #define ASTOBJ_CONTAINER_MARKALL(container) \
- ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_MARK(iterator))
- /*! \brief Unmark all the objects in a container.
- * \param container A pointer to the container to operate on.
- */
- #define ASTOBJ_CONTAINER_UNMARKALL(container) \
- ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_UNMARK(iterator))
- /*! \brief Dump information about an object into a string.
- *
- * \param s A pointer to the string buffer to use.
- * \param slen The length of s.
- * \param obj A pointer to the object to dump.
- *
- * This macro dumps a text representation of the name, objectflags, and
- * refcount fields of an object to the specfied string buffer.
- */
- #define ASTOBJ_DUMP(s,slen,obj) \
- snprintf((s),(slen),"name: %s\nobjflags: %u\nrefcount: %u\n\n", (obj)->name, (obj)->objflags, (obj)->refcount);
- /*! \brief Dump information about all the objects in a container to a file descriptor.
- *
- * \param fd The file descriptor to write to.
- * \param s A string buffer, same as #ASTOBJ_DUMP().
- * \param slen The length of s, same as #ASTOBJ_DUMP().
- * \param container A pointer to the container to dump.
- *
- * This macro dumps a text representation of the name, objectflags, and
- * refcount fields of all the objects in a container to the specified file
- * descriptor.
- */
- #define ASTOBJ_CONTAINER_DUMP(fd,s,slen,container) \
- ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { ASTOBJ_DUMP(s,slen,iterator); ast_cli(fd, "%s", s); } while(0))
- #if defined(__cplusplus) || defined(c_plusplus)
- }
- #endif
- #endif /* _ASTERISK_ASTOBJ_H */
|