Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:49 2009

## Asterisk developer's documentation

# astobj.h

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*
    00020  * Object Model for Asterisk
    00021  */
    00022
    00023 #ifndef _ASTERISK_ASTOBJ_H
    00024 #define _ASTERISK_ASTOBJ_H
    00025
    00026 #include <string.h>
    00027
    00028 #include "asterisk/lock.h"
    00029 #include "asterisk/compiler.h"
    00030
    00031 /*! \file
    00032  * \brief A set of macros implementing objects and containers.
    00033  * Macros are used for maximum performance, to support multiple inheritance,
    00034  * and to be easily integrated into existing structures without additional
    00035  * malloc calls, etc.
    00036  *
    00037  * These macros expect to operate on two different object types, ASTOBJs and
    00038  * ASTOBJ_CONTAINERs.  These are not actual types, as any struct can be
    00039  * converted into an ASTOBJ compatible object or container using the supplied
    00040  * macros.
    00041  *
    00042  * <b>Sample Usage:</b>
    00043  * \code
    00044  * struct sample_object {
    00045  *    ASTOBJ_COMPONENTS(struct sample_object);
    00046  * };
    00047  *
    00048  * struct sample_container {
    00049  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_object);
    00050  * } super_container;
    00051  *
    00052  * void sample_object_destroy(struct sample_object *obj)
    00053  * {
    00054  *    free(obj);
    00055  * }
    00056  *
    00057  * int init_stuff()
    00058  * {
    00059  *    struct sample_object *obj1;
    00060  *    struct sample_object *found_obj;
    00061  *
    00062  *    obj1 = malloc(sizeof(struct sample_object));
    00063  *
    00064  *    ASTOBJ_CONTAINER_INIT(&super_container);
    00065  *
    00066  *    ASTOBJ_INIT(obj1);
    00067  *    ASTOBJ_WRLOCK(obj1);
    00068  *    ast_copy_string(obj1->name, "obj1", sizeof(obj1->name));
    00069  *    ASTOBJ_UNLOCK(obj1);
    00070  *
    00071  *    ASTOBJ_CONTAINER_LINK(&super_container, obj1);
    00072  *
    00073  *    found_obj = ASTOBJ_CONTAINER_FIND(&super_container, "obj1");
    00074  *
    00075  *    if(found_obj) {
    00076  *       printf("Found object: %s", found_obj->name);
    00077  *       ASTOBJ_UNREF(found_obj,sample_object_destroy);
    00078  *    }
    00079  *
    00080  *    ASTOBJ_CONTAINER_DESTROYALL(&super_container,sample_object_destroy);
    00081  *    ASTOBJ_CONTAINER_DESTROY(&super_container);
    00082  *
    00083  *    return 0;
    00084  * }
    00085  * \endcode
    00086  */
    00087
    00088 #if defined(__cplusplus) || defined(c_plusplus)
    00089 extern "C" {
    00090 #endif
    00091
    00092 #define ASTOBJ_DEFAULT_NAMELEN   80
    00093 #define ASTOBJ_DEFAULT_BUCKETS   256
    00094 #define ASTOBJ_DEFAULT_HASH      ast_strhash
    00095
    00096 #define ASTOBJ_FLAG_MARKED (1 << 0)    /* Object has been marked for future operation */
    00097
    00098 /* C++ is simply a syntactic crutch for those who cannot think for themselves
    00099    in an object oriented way. */
    00100
    00101 /*! \brief Lock an ASTOBJ for reading.
    00102  */
    00103 #define ASTOBJ_RDLOCK(object) ast_mutex_lock(&(object)->_lock)
    00104
    00105 /*! \brief Lock an ASTOBJ for writing.
    00106  */
    00107 #define ASTOBJ_WRLOCK(object) ast_mutex_lock(&(object)->_lock)
    00108
    00109 /*! \brief Unlock a locked object. */
    00110 #define ASTOBJ_UNLOCK(object) ast_mutex_unlock(&(object)->_lock)
    00111
    00112 #ifdef ASTOBJ_CONTAINER_HASHMODEL
    00113 #define __ASTOBJ_HASH(type,hashes) \
    00114    type *next[hashes]
    00115 #else
    00116 #define __ASTOBJ_HASH(type,hashes) \
    00117    type *next[1]
    00118 #endif
    00119
    00120 /*! \brief Add ASTOBJ components to a struct (without locking support).
    00121  *
    00122  * \param type The datatype of the object.
    00123  * \param namelen The length to make the name char array.
    00124  * \param hashes The number of containers the object can be present in.
    00125  *
    00126  * This macro adds components to a struct to make it an ASTOBJ.  This macro
    00127  * differs from ASTOBJ_COMPONENTS_FULL in that it does not create a mutex for
    00128  * locking.
    00129  *
    00130  * <b>Sample Usage:</b>
    00131  * \code
    00132  * struct sample_struct {
    00133  *    ASTOBJ_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
    00134  * };
    00135  * \endcode
    00136  */
    00137 #define ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes) \
    00138    char name[namelen]; \
    00139    unsigned int refcount; \
    00140    unsigned int objflags; \
    00141    __ASTOBJ_HASH(type,hashes)
    00142
    00143 /*! \brief Add ASTOBJ components to a struct (without locking support).
    00144  *
    00145  * \param type The datatype of the object.
    00146  *
    00147  * This macro works like #ASTOBJ_COMPONENTS_NOLOCK_FULL() except it only accepts a
    00148  * type and uses default values for namelen and hashes.
    00149  *
    00150  * <b>Sample Usage:</b>
    00151  * \code
    00152  * struct sample_struct_componets {
    00153  *    ASTOBJ_COMPONENTS_NOLOCK(struct sample_struct);
    00154  * };
    00155  * \endcode
    00156  */
    00157 #define ASTOBJ_COMPONENTS_NOLOCK(type) \
    00158    ASTOBJ_COMPONENTS_NOLOCK_FULL(type,ASTOBJ_DEFAULT_NAMELEN,1)
    00159
    00160 /*! \brief Add ASTOBJ components to a struct (with locking support).
    00161  *
    00162  * \param type The datatype of the object.
    00163  *
    00164  * This macro works like #ASTOBJ_COMPONENTS_NOLOCK() except it includes locking
    00165  * support.
    00166  *
    00167  * <b>Sample Usage:</b>
    00168  * \code
    00169  * struct sample_struct {
    00170  *    ASTOBJ_COMPONENTS(struct sample_struct);
    00171  * };
    00172  * \endcode
    00173  */
    00174 #define ASTOBJ_COMPONENTS(type) \
    00175    ASTOBJ_COMPONENTS_NOLOCK(type); \
    00176    ast_mutex_t _lock;
    00177
    00178 /*! \brief Add ASTOBJ components to a struct (with locking support).
    00179  *
    00180  * \param type The datatype of the object.
    00181  * \param namelen The length to make the name char array.
    00182  * \param hashes The number of containers the object can be present in.
    00183  *
    00184  * This macro adds components to a struct to make it an ASTOBJ and includes
    00185  * support for locking.
    00186  *
    00187  * <b>Sample Usage:</b>
    00188  * \code
    00189  * struct sample_struct {
    00190  *    ASTOBJ_COMPONENTS_FULL(struct sample_struct,1,1);
    00191  * };
    00192  * \endcode
    00193  */
    00194 #define ASTOBJ_COMPONENTS_FULL(type,namelen,hashes) \
    00195    ASTOBJ_COMPONENTS_NOLOCK_FULL(type,namelen,hashes); \
    00196    ast_mutex_t _lock;
    00197
    00198 /*! \brief Increment an object reference count.
    00199  * \param object A pointer to the object to operate on.
    00200  * \return The object.
    00201  */
    00202 #define ASTOBJ_REF(object) \
    00203    ({ \
    00204       ASTOBJ_WRLOCK(object); \
    00205       (object)->refcount++; \
    00206       ASTOBJ_UNLOCK(object); \
    00207       (object); \
    00208    })
    00209
    00210 /*! \brief Decrement the reference count on an object.
    00211  *
    00212  * \param object A pointer the object to operate on.
    00213  * \param destructor The destructor to call if the object is no longer referenced.  It will be passed the pointer as an argument.
    00214  *
    00215  * This macro unreferences an object and calls the specfied destructor if the
    00216  * object is no longer referenced.  The destructor should free the object if it
    00217  * was dynamically allocated.
    00218  */
    00219 #define ASTOBJ_UNREF(object,destructor) \
    00220    do { \
    00221       int newcount = 0; \
    00222       ASTOBJ_WRLOCK(object); \
    00223       if (__builtin_expect((object)->refcount > 0, 1)) \
    00224          newcount = --((object)->refcount); \
    00225       else \
    00226          ast_log(LOG_WARNING, "Unreferencing unreferenced (object)!\n"); \
    00227       ASTOBJ_UNLOCK(object); \
    00228       if (newcount == 0) { \
    00229          ast_mutex_destroy(&(object)->_lock); \
    00230          destructor((object)); \
    00231       } \
    00232       (object) = NULL; \
    00233    } while(0)
    00234
    00235 /*! \brief Mark an ASTOBJ by adding the #ASTOBJ_FLAG_MARKED flag to its objflags mask.
    00236  * \param object A pointer to the object to operate on.
    00237  *
    00238  * This macro "marks" an object.  Marked objects can later be unlinked from a container using
    00239  * #ASTOBJ_CONTAINER_PRUNE_MARKED().
    00240  *
    00241  */
    00242 #define ASTOBJ_MARK(object) \
    00243    do { \
    00244       ASTOBJ_WRLOCK(object); \
    00245       (object)->objflags |= ASTOBJ_FLAG_MARKED; \
    00246       ASTOBJ_UNLOCK(object); \
    00247    } while(0)
    00248
    00249 /*! \brief Unmark an ASTOBJ by subtracting the #ASTOBJ_FLAG_MARKED flag from its objflags mask.
    00250  * \param object A pointer to the object to operate on.
    00251  */
    00252 #define ASTOBJ_UNMARK(object) \
    00253    do { \
    00254       ASTOBJ_WRLOCK(object); \
    00255       (object)->objflags &= ~ASTOBJ_FLAG_MARKED; \
    00256       ASTOBJ_UNLOCK(object); \
    00257    } while(0)
    00258
    00259 /*! \brief Initialize an object.
    00260  * \param object A pointer to the object to operate on.
    00261  *
    00262  * \note This should only be used on objects that support locking (objects
    00263  * created with #ASTOBJ_COMPONENTS() or #ASTOBJ_COMPONENTS_FULL())
    00264  */
    00265 #define ASTOBJ_INIT(object) \
    00266    do { \
    00267       ast_mutex_init(&(object)->_lock); \
    00268       object->name[0] = '\0'; \
    00269       object->refcount = 1; \
    00270    } while(0)
    00271
    00272 /* Containers for objects -- current implementation is linked lists, but
    00273    should be able to be converted to hashes relatively easily */
    00274
    00275 /*! \brief Lock an ASTOBJ_CONTAINER for reading.
    00276  */
    00277 #define ASTOBJ_CONTAINER_RDLOCK(container) ast_mutex_lock(&(container)->_lock)
    00278
    00279 /*! \brief Lock an ASTOBJ_CONTAINER for writing.
    00280  */
    00281 #define ASTOBJ_CONTAINER_WRLOCK(container) ast_mutex_lock(&(container)->_lock)
    00282
    00283 /*! \brief Unlock an ASTOBJ_CONTAINER. */
    00284 #define ASTOBJ_CONTAINER_UNLOCK(container) ast_mutex_unlock(&(container)->_lock)
    00285
    00286 #ifdef ASTOBJ_CONTAINER_HASHMODEL
    00287 #error "Hash model for object containers not yet implemented!"
    00288 #else
    00289 /* Linked lists */
    00290
    00291 /*! \brief Create a container for ASTOBJs (without locking support).
    00292  *
    00293  * \param type The type of objects the container will hold.
    00294  * \param hashes Currently unused.
    00295  * \param buckets Currently unused.
    00296  *
    00297  * This macro is used to create a container for ASTOBJs without locking
    00298  * support.
    00299  *
    00300  * <b>Sample Usage:</b>
    00301  * \code
    00302  * struct sample_struct_nolock_container {
    00303  *    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(struct sample_struct,1,1);
    00304  * };
    00305  * \endcode
    00306  */
    00307 #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,hashes,buckets) \
    00308    type *head
    00309
    00310 /*! \brief Initialize a container.
    00311  *
    00312  * \param container A pointer to the container to initialize.
    00313  * \param hashes Currently unused.
    00314  * \param buckets Currently unused.
    00315  *
    00316  * This macro initializes a container.  It should only be used on containers
    00317  * that support locking.
    00318  *
    00319  * <b>Sample Usage:</b>
    00320  * \code
    00321  * struct sample_struct_container {
    00322  *    ASTOBJ_CONTAINER_COMPONENTS_FULL(struct sample_struct,1,1);
    00323  * } container;
    00324  *
    00325  * int func()
    00326  * {
    00327  *    ASTOBJ_CONTAINER_INIT_FULL(&container,1,1);
    00328  * }
    00329  * \endcode
    00330  */
    00331 #define ASTOBJ_CONTAINER_INIT_FULL(container,hashes,buckets) \
    00332    do { \
    00333       ast_mutex_init(&(container)->_lock); \
    00334    } while(0)
    00335
    00336 /*! \brief Destroy a container.
    00337  *
    00338  * \param container A pointer to the container to destroy.
    00339  * \param hashes Currently unused.
    00340  * \param buckets Currently unused.
    00341  *
    00342  * This macro frees up resources used by a container.  It does not operate on
    00343  * the objects in the container.  To unlink the objects from the container use
    00344  * #ASTOBJ_CONTAINER_DESTROYALL().
    00345  *
    00346  * \note This macro should only be used on containers with locking support.
    00347  */
    00348 #define ASTOBJ_CONTAINER_DESTROY_FULL(container,hashes,buckets) \
    00349    do { \
    00350       ast_mutex_destroy(&(container)->_lock); \
    00351    } while(0)
    00352
    00353 /*! \brief Iterate through the objects in a container.
    00354  *
    00355  * \param container A pointer to the container to traverse.
    00356  * \param continue A condition to allow the traversal to continue.
    00357  * \param eval A statement to evaluate in the iteration loop.
    00358  *
    00359  * This is macro is a little complicated, but it may help to think of it as a
    00360  * loop.  Basically it iterates through the specfied containter as long as the
    00361  * condition is met.  Two variables, iterator and next, are provided for use in
    00362  * your \p eval statement.  See the sample code for an example.
    00363  *
    00364  * <b>Sample Usage:</b>
    00365  * \code
    00366  * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, {
    00367  *    ASTOBJ_RDLOCK(iterator);
    00368  *    printf("Currently iterating over '%s'\n", iterator->name);
    00369  *    ASTOBJ_UNLOCK(iterator);
    00370  * } );
    00371  * \endcode
    00372  *
    00373  * \code
    00374  * ASTOBJ_CONTAINER_TRAVERSE(&sample_container,1, sample_func(iterator));
    00375  * \endcode
    00376  */
    00377 #define ASTOBJ_CONTAINER_TRAVERSE(container,continue,eval) \
    00378    do { \
    00379       typeof((container)->head) iterator; \
    00380       typeof((container)->head) next; \
    00381       ASTOBJ_CONTAINER_RDLOCK(container); \
    00382       next = (container)->head; \
    00383       while((continue) && (iterator = next)) { \
    00384          next = iterator->next[0]; \
    00385          eval; \
    00386       } \
    00387       ASTOBJ_CONTAINER_UNLOCK(container); \
    00388    } while(0)
    00389
    00390 /*! \brief Find an object in a container.
    00391  *
    00392  * \param container A pointer to the container to search.
    00393  * \param namestr The name to search for.
    00394  *
    00395  * Use this function to find an object with the specfied name in a container.
    00396  *
    00397  * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
    00398  * be used to free the additional reference created by this macro.
    00399  *
    00400  * \return A new reference to the object located or NULL if nothing is found.
    00401  */
    00402 #define ASTOBJ_CONTAINER_FIND(container,namestr) \
    00403    ({ \
    00404       typeof((container)->head) found = NULL; \
    00405       ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
    00406          if (!(strcasecmp(iterator->name, (namestr)))) \
    00407             found = ASTOBJ_REF(iterator); \
    00408       } while (0)); \
    00409       found; \
    00410    })
    00411
    00412 /*! \brief Find an object in a container.
    00413  *
    00414  * \param container A pointer to the container to search.
    00415  * \param data The data to search for.
    00416  * \param field The field/member of the container's objects to search.
    00417  * \param hashfunc The hash function to use, currently not implemented.
    00418  * \param hashoffset The hash offset to use, currently not implemented.
    00419  * \param comparefunc The function used to compare the field and data values.
    00420  *
    00421  * This macro iterates through a container passing the specified field and data
    00422  * elements to the specified comparefunc.  The function should return 0 when a match is found.
    00423  *
    00424  * \note When the returned object is no longer in use, #ASTOBJ_UNREF() should
    00425  * be used to free the additional reference created by this macro.
    00426  *
    00427  * \return A pointer to the object located or NULL if nothing is found.
    00428  */
    00429 #define ASTOBJ_CONTAINER_FIND_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
    00430    ({ \
    00431       typeof((container)->head) found = NULL; \
    00432       ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
    00433          ASTOBJ_RDLOCK(iterator); \
    00434          if (!(comparefunc(iterator->field, (data)))) { \
    00435             found = ASTOBJ_REF(iterator); \
    00436          } \
    00437          ASTOBJ_UNLOCK(iterator); \
    00438       } while (0)); \
    00439       found; \
    00440    })
    00441
    00442 /*! \brief Empty a container.
    00443  *
    00444  * \param container A pointer to the container to operate on.
    00445  * \param destructor A destructor function to call on each object.
    00446  *
    00447  * This macro loops through a container removing all the items from it using
    00448  * #ASTOBJ_UNREF().  This does not destroy the container itself, use
    00449  * #ASTOBJ_CONTAINER_DESTROY() for that.
    00450  *
    00451  * \note If any object in the container is only referenced by the container,
    00452  * the destructor will be called for that object once it has been removed.
    00453  */
    00454 #define ASTOBJ_CONTAINER_DESTROYALL(container,destructor) \
    00455    do { \
    00456       typeof((container)->head) iterator; \
    00457       ASTOBJ_CONTAINER_WRLOCK(container); \
    00458       while((iterator = (container)->head)) { \
    00459          (container)->head = (iterator)->next[0]; \
    00460          ASTOBJ_UNREF(iterator,destructor); \
    00461       } \
    00462       ASTOBJ_CONTAINER_UNLOCK(container); \
    00463    } while(0)
    00464
    00465 /*! \brief Remove an object from a container.
    00466  *
    00467  * \param container A pointer to the container to operate on.
    00468  * \param obj A pointer to the object to remove.
    00469  *
    00470  * This macro iterates through a container and removes the specfied object if
    00471  * it exists in the container.
    00472  *
    00473  * \note This macro does not destroy any objects, it simply unlinks
    00474  * them from the list.  No destructors are called.
    00475  *
    00476  * \return The container's reference to the removed object or NULL if no
    00477  * matching object was found.
    00478  */
    00479 #define ASTOBJ_CONTAINER_UNLINK(container,obj) \
    00480    ({ \
    00481       typeof((container)->head) found = NULL; \
    00482       typeof((container)->head) prev = NULL; \
    00483       ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
    00484          if (iterator == obj) { \
    00485             found = iterator; \
    00486             found->next[0] = NULL; \
    00487             ASTOBJ_CONTAINER_WRLOCK(container); \
    00488             if (prev) \
    00489                prev->next[0] = next; \
    00490             else \
    00491                (container)->head = next; \
    00492             ASTOBJ_CONTAINER_UNLOCK(container); \
    00493          } \
    00494          prev = iterator; \
    00495       } while (0)); \
    00496       found; \
    00497    })
    00498
    00499 /*! \brief Find and remove an object from a container.
    00500  *
    00501  * \param container A pointer to the container to operate on.
    00502  * \param namestr The name of the object to remove.
    00503  *
    00504  * This macro iterates through a container and removes the first object with
    00505  * the specfied name from the container.
    00506  *
    00507  * \note This macro does not destroy any objects, it simply unlinks
    00508  * them.  No destructors are called.
    00509  *
    00510  * \return The container's reference to the removed object or NULL if no
    00511  * matching object was found.
    00512  */
    00513 #define ASTOBJ_CONTAINER_FIND_UNLINK(container,namestr) \
    00514    ({ \
    00515       typeof((container)->head) found = NULL; \
    00516       typeof((container)->head) prev = NULL; \
    00517       ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
    00518          if (!(strcasecmp(iterator->name, (namestr)))) { \
    00519             found = iterator; \
    00520             found->next[0] = NULL; \
    00521             ASTOBJ_CONTAINER_WRLOCK(container); \
    00522             if (prev) \
    00523                prev->next[0] = next; \
    00524             else \
    00525                (container)->head = next; \
    00526             ASTOBJ_CONTAINER_UNLOCK(container); \
    00527          } \
    00528          prev = iterator; \
    00529       } while (0)); \
    00530       found; \
    00531    })
    00532
    00533 /*! \brief Find and remove an object in a container.
    00534  *
    00535  * \param container A pointer to the container to search.
    00536  * \param data The data to search for.
    00537  * \param field The field/member of the container's objects to search.
    00538  * \param hashfunc The hash function to use, currently not implemented.
    00539  * \param hashoffset The hash offset to use, currently not implemented.
    00540  * \param comparefunc The function used to compare the field and data values.
    00541  *
    00542  * This macro iterates through a container passing the specified field and data
    00543  * elements to the specified comparefunc.  The function should return 0 when a match is found.
    00544  * If a match is found it is removed from the list.
    00545  *
    00546  * \note This macro does not destroy any objects, it simply unlinks
    00547  * them.  No destructors are called.
    00548  *
    00549  * \return The container's reference to the removed object or NULL if no match
    00550  * was found.
    00551  */
    00552 #define ASTOBJ_CONTAINER_FIND_UNLINK_FULL(container,data,field,hashfunc,hashoffset,comparefunc) \
    00553    ({ \
    00554       typeof((container)->head) found = NULL; \
    00555       typeof((container)->head) prev = NULL; \
    00556       ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
    00557          ASTOBJ_RDLOCK(iterator); \
    00558          if (!(comparefunc(iterator->field, (data)))) { \
    00559             found = iterator; \
    00560             found->next[0] = NULL; \
    00561             ASTOBJ_CONTAINER_WRLOCK(container); \
    00562             if (prev) \
    00563                prev->next[0] = next; \
    00564             else \
    00565                (container)->head = next; \
    00566             ASTOBJ_CONTAINER_UNLOCK(container); \
    00567          } \
    00568          ASTOBJ_UNLOCK(iterator); \
    00569          prev = iterator; \
    00570       } while (0)); \
    00571       found; \
    00572    })
    00573
    00574 /*! \brief Prune marked objects from a container.
    00575  *
    00576  * \param container A pointer to the container to prune.
    00577  * \param destructor A destructor function to call on each marked object.
    00578  *
    00579  * This macro iterates through the specfied container and prunes any marked
    00580  * objects executing the specfied destructor if necessary.
    00581  */
    00582 #define ASTOBJ_CONTAINER_PRUNE_MARKED(container,destructor) \
    00583    do { \
    00584       typeof((container)->head) prev = NULL; \
    00585       ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { \
    00586          ASTOBJ_RDLOCK(iterator); \
    00587          if (iterator->objflags & ASTOBJ_FLAG_MARKED) { \
    00588             ASTOBJ_CONTAINER_WRLOCK(container); \
    00589             if (prev) \
    00590                prev->next[0] = next; \
    00591             else \
    00592                (container)->head = next; \
    00593             ASTOBJ_CONTAINER_UNLOCK(container); \
    00594             ASTOBJ_UNLOCK(iterator); \
    00595             ASTOBJ_UNREF(iterator,destructor); \
    00596             continue; \
    00597          } \
    00598          ASTOBJ_UNLOCK(iterator); \
    00599          prev = iterator; \
    00600       } while (0)); \
    00601    } while(0)
    00602
    00603 /*! \brief Add an object to a container.
    00604  *
    00605  * \param container A pointer to the container to operate on.
    00606  * \param newobj A pointer to the object to be added.
    00607  * \param data Currently unused.
    00608  * \param field Currently unused.
    00609  * \param hashfunc Currently unused.
    00610  * \param hashoffset Currently unused.
    00611  * \param comparefunc Currently unused.
    00612  *
    00613  * Currently this function adds an object to the head of the list.  One day it
    00614  * will support adding objects atthe position specified using the various
    00615  * options this macro offers.
    00616  */
    00617 #define ASTOBJ_CONTAINER_LINK_FULL(container,newobj,data,field,hashfunc,hashoffset,comparefunc) \
    00618    do { \
    00619       ASTOBJ_CONTAINER_WRLOCK(container); \
    00620       (newobj)->next[0] = (container)->head; \
    00621       (container)->head = ASTOBJ_REF(newobj); \
    00622       ASTOBJ_CONTAINER_UNLOCK(container); \
    00623    } while(0)
    00624
    00625 #endif /* List model */
    00626
    00627 /* Common to hash and linked list models */
    00628
    00629 /*! \brief Create a container for ASTOBJs (without locking support).
    00630  *
    00631  * \param type The type of objects the container will hold.
    00632  *
    00633  * This macro is used to create a container for ASTOBJs without locking
    00634  * support.
    00635  *
    00636  * <b>Sample Usage:</b>
    00637  * \code
    00638  * struct sample_struct_nolock_container {
    00639  *    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(struct sample_struct);
    00640  * };
    00641  * \endcode
    00642  */
    00643 #define ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type) \
    00644    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK_FULL(type,1,ASTOBJ_DEFAULT_BUCKETS)
    00645
    00646
    00647 /*! \brief Create a container for ASTOBJs (with locking support).
    00648  *
    00649  * \param type The type of objects the container will hold.
    00650  *
    00651  * This macro is used to create a container for ASTOBJs with locking support.
    00652  *
    00653  * <b>Sample Usage:</b>
    00654  * \code
    00655  * struct sample_struct_container {
    00656  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
    00657  * };
    00658  * \endcode
    00659  */
    00660 #define ASTOBJ_CONTAINER_COMPONENTS(type) \
    00661    ast_mutex_t _lock; \
    00662    ASTOBJ_CONTAINER_COMPONENTS_NOLOCK(type)
    00663
    00664 /*! \brief Initialize a container.
    00665  *
    00666  * \param container A pointer to the container to initialize.
    00667  *
    00668  * This macro initializes a container.  It should only be used on containers
    00669  * that support locking.
    00670  *
    00671  * <b>Sample Usage:</b>
    00672  * \code
    00673  * struct sample_struct_container {
    00674  *    ASTOBJ_CONTAINER_COMPONENTS(struct sample_struct);
    00675  * } container;
    00676  *
    00677  * int func()
    00678  * {
    00679  *    ASTOBJ_CONTAINER_INIT(&container);
    00680  * }
    00681  * \endcode
    00682  */
    00683 #define ASTOBJ_CONTAINER_INIT(container) \
    00684    ASTOBJ_CONTAINER_INIT_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
    00685
    00686 /*! \brief Destroy a container.
    00687  *
    00688  * \param container A pointer to the container to destory.
    00689  *
    00690  * This macro frees up resources used by a container.  It does not operate on
    00691  * the objects in the container.  To unlink the objects from the container use
    00692  * #ASTOBJ_CONTAINER_DESTROYALL().
    00693  *
    00694  * \note This macro should only be used on containers with locking support.
    00695  */
    00696 #define ASTOBJ_CONTAINER_DESTROY(container) \
    00697    ASTOBJ_CONTAINER_DESTROY_FULL(container,1,ASTOBJ_DEFAULT_BUCKETS)
    00698
    00699 /*! \brief Add an object to a container.
    00700  *
    00701  * \param container A pointer to the container to operate on.
    00702  * \param newobj A pointer to the object to be added.
    00703  *
    00704  * Currently this macro adds an object to the head of a container.  One day it
    00705  * should add an object in alphabetical order.
    00706  */
    00707 #define ASTOBJ_CONTAINER_LINK(container,newobj) \
    00708    ASTOBJ_CONTAINER_LINK_FULL(container,newobj,(newobj)->name,name,ASTOBJ_DEFAULT_HASH,0,strcasecmp)
    00709
    00710 /*! \brief Mark all the objects in a container.
    00711  * \param container A pointer to the container to operate on.
    00712  */
    00713 #define ASTOBJ_CONTAINER_MARKALL(container) \
    00714    ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_MARK(iterator))
    00715
    00716 /*! \brief Unmark all the objects in a container.
    00717  * \param container A pointer to the container to operate on.
    00718  */
    00719 #define ASTOBJ_CONTAINER_UNMARKALL(container) \
    00720    ASTOBJ_CONTAINER_TRAVERSE(container, 1, ASTOBJ_UNMARK(iterator))
    00721
    00722 /*! \brief Dump information about an object into a string.
    00723  *
    00724  * \param s A pointer to the string buffer to use.
    00725  * \param slen The length of s.
    00726  * \param obj A pointer to the object to dump.
    00727  *
    00728  * This macro dumps a text representation of the name, objectflags, and
    00729  * refcount fields of an object to the specfied string buffer.
    00730  */
    00731 #define ASTOBJ_DUMP(s,slen,obj) \
    00732    snprintf((s),(slen),"name: %s\nobjflags: %d\nrefcount: %d\n\n", (obj)->name, (obj)->objflags, (obj)->refcount);
    00733
    00734 /*! \brief Dump information about all the objects in a container to a file descriptor.
    00735  *
    00736  * \param fd The file descriptor to write to.
    00737  * \param s A string buffer, same as #ASTOBJ_DUMP().
    00738  * \param slen The length of s, same as #ASTOBJ_DUMP().
    00739  * \param container A pointer to the container to dump.
    00740  *
    00741  * This macro dumps a text representation of the name, objectflags, and
    00742  * refcount fields of all the objects in a container to the specified file
    00743  * descriptor.
    00744  */
    00745 #define ASTOBJ_CONTAINER_DUMP(fd,s,slen,container) \
    00746    ASTOBJ_CONTAINER_TRAVERSE(container, 1, do { ASTOBJ_DUMP(s,slen,iterator); ast_cli(fd, "%s", s); } while(0))
    00747
    00748 #if defined(__cplusplus) || defined(c_plusplus)
    00749 }
    00750 #endif
    00751
    00752 #endif /* _ASTERISK_ASTOBJ_H */