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

Generated on Thu Apr 16 06:27:14 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6