astobj2_container_private.h

Go to the documentation of this file.
00001 /*
00002  * astobj2 - replacement containers for asterisk data structures.
00003  *
00004  * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief Common, private definitions for astobj2 containers.
00020  *
00021  * \author Richard Mudgett <rmudgett@digium.com>
00022  */
00023 
00024 #ifndef ASTOBJ2_CONTAINER_PRIVATE_H_
00025 #define ASTOBJ2_CONTAINER_PRIVATE_H_
00026 
00027 #include "asterisk/astobj2.h"
00028 
00029 /*!
00030  * \internal
00031  * \brief Enum for internal_ao2_unlink_node.
00032  */
00033 enum ao2_unlink_node_flags {
00034    /*! Remove the node from the object's weak link list
00035     * OR unref the object if it's a strong reference. */
00036    AO2_UNLINK_NODE_UNLINK_OBJECT = (1 << 0),
00037    /*! Modified unlink_object to skip the unref of the object. */
00038    AO2_UNLINK_NODE_NOUNREF_OBJECT = (1 << 1),
00039    /*! Unref the node. */
00040    AO2_UNLINK_NODE_UNREF_NODE = (1 << 2),
00041    /*! Decrement the container's element count. */
00042    AO2_UNLINK_NODE_DEC_COUNT = (1 << 3),
00043 };
00044 
00045 enum ao2_callback_type {
00046    AO2_CALLBACK_DEFAULT,
00047    AO2_CALLBACK_WITH_DATA,
00048 };
00049 
00050 enum ao2_container_insert {
00051    /*! The node was inserted into the container. */
00052    AO2_CONTAINER_INSERT_NODE_INSERTED,
00053    /*! The node object replaced an existing node object. */
00054    AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED,
00055    /*! The node was rejected (duplicate). */
00056    AO2_CONTAINER_INSERT_NODE_REJECTED,
00057 };
00058 
00059 /*! Allow enough room for container specific traversal state structs */
00060 #define AO2_TRAVERSAL_STATE_SIZE 100
00061 
00062 /*!
00063  * \brief Generic container node.
00064  *
00065  * \details This is the base container node type that contains
00066  * values common to all container nodes.
00067  */
00068 struct ao2_container_node {
00069    /*! Stored object in node. */
00070    void *obj;
00071    /*! Container holding the node.  (Does not hold a reference.) */
00072    struct ao2_container *my_container;
00073    /*! TRUE if the node is linked into the container. */
00074    unsigned int is_linked:1;
00075 };
00076 
00077 /*!
00078  * \brief Destroy this container.
00079  *
00080  * \param self Container to operate upon.
00081  *
00082  * \return Nothing
00083  */
00084 typedef void (*ao2_container_destroy_fn)(struct ao2_container *self);
00085 
00086 /*!
00087  * \brief Create an empty copy of this container.
00088  *
00089  * \param self Container to operate upon.
00090  *
00091  * \retval empty-container on success.
00092  * \retval NULL on error.
00093  */
00094 typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self);
00095 
00096 /*!
00097  * \brief Create an empty copy of this container. (Debug version)
00098  *
00099  * \param self Container to operate upon.
00100  * \param tag used for debugging.
00101  * \param file Debug file name invoked from
00102  * \param line Debug line invoked from
00103  * \param func Debug function name invoked from
00104  * \param ref_debug TRUE if to output a debug reference message.
00105  *
00106  * \retval empty-container on success.
00107  * \retval NULL on error.
00108  */
00109 typedef struct ao2_container *(*ao2_container_alloc_empty_clone_debug_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func, int ref_debug);
00110 
00111 /*!
00112  * \brief Create a new container node.
00113  *
00114  * \param self Container to operate upon.
00115  * \param obj_new Object to put into the node.
00116  * \param tag used for debugging.
00117  * \param file Debug file name invoked from
00118  * \param line Debug line invoked from
00119  * \param func Debug function name invoked from
00120  *
00121  * \retval initialized-node on success.
00122  * \retval NULL on error.
00123  */
00124 typedef struct ao2_container_node *(*ao2_container_new_node_fn)(struct ao2_container *self, void *obj_new, const char *tag, const char *file, int line, const char *func);
00125 
00126 /*!
00127  * \brief Insert a node into this container.
00128  *
00129  * \param self Container to operate upon.
00130  * \param node Container node to insert into the container.
00131  *
00132  * \return enum ao2_container_insert value.
00133  */
00134 typedef enum ao2_container_insert (*ao2_container_insert_fn)(struct ao2_container *self, struct ao2_container_node *node);
00135 
00136 /*!
00137  * \brief Find the first container node in a traversal.
00138  *
00139  * \param self Container to operate upon.
00140  * \param flags search_flags to control traversing the container
00141  * \param arg Comparison callback arg parameter.
00142  * \param v_state Traversal state to restart container traversal.
00143  *
00144  * \retval node-ptr of found node (Reffed).
00145  * \retval NULL when no node found.
00146  */
00147 typedef struct ao2_container_node *(*ao2_container_find_first_fn)(struct ao2_container *self, enum search_flags flags, void *arg, void *v_state);
00148 
00149 /*!
00150  * \brief Find the next container node in a traversal.
00151  *
00152  * \param self Container to operate upon.
00153  * \param v_state Traversal state to restart container traversal.
00154  * \param prev Previous node returned by the traversal search functions.
00155  *    The ref ownership is passed back to this function.
00156  *
00157  * \retval node-ptr of found node (Reffed).
00158  * \retval NULL when no node found.
00159  */
00160 typedef struct ao2_container_node *(*ao2_container_find_next_fn)(struct ao2_container *self, void *v_state, struct ao2_container_node *prev);
00161 
00162 /*!
00163  * \brief Cleanup the container traversal state.
00164  *
00165  * \param v_state Traversal state to cleanup.
00166  *
00167  * \return Nothing
00168  */
00169 typedef void (*ao2_container_find_cleanup_fn)(void *v_state);
00170 
00171 /*!
00172  * \brief Find the next non-empty iteration node in the container.
00173  *
00174  * \param self Container to operate upon.
00175  * \param prev Previous node returned by the iterator.
00176  * \param flags search_flags to control iterating the container.
00177  *   Only AO2_ITERATOR_DESCENDING is useful by the method.
00178  *
00179  * \note The container is already locked.
00180  *
00181  * \retval node on success.
00182  * \retval NULL on error or no more nodes in the container.
00183  */
00184 typedef struct ao2_container_node *(*ao2_iterator_next_fn)(struct ao2_container *self, struct ao2_container_node *prev, enum ao2_iterator_flags flags);
00185 
00186 /*!
00187  * \brief Display contents of the specified container.
00188  *
00189  * \param self Container to dump.
00190  * \param where User data needed by prnt to determine where to put output.
00191  * \param prnt Print output callback function to use.
00192  * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
00193  *
00194  * \return Nothing
00195  */
00196 typedef void (*ao2_container_display)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj);
00197 
00198 /*!
00199  * \brief Display statistics of the specified container.
00200  *
00201  * \param self Container to display statistics.
00202  * \param where User data needed by prnt to determine where to put output.
00203  * \param prnt Print output callback function to use.
00204  *
00205  * \note The container is already locked for reading.
00206  *
00207  * \return Nothing
00208  */
00209 typedef void (*ao2_container_statistics)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt);
00210 
00211 /*!
00212  * \brief Perform an integrity check on the specified container.
00213  *
00214  * \param self Container to check integrity.
00215  *
00216  * \note The container is already locked for reading.
00217  *
00218  * \retval 0 on success.
00219  * \retval -1 on error.
00220  */
00221 typedef int (*ao2_container_integrity)(struct ao2_container *self);
00222 
00223 /*!
00224  * \internal
00225  * \brief Increment the container linked object statistic.
00226  * \since 12.4.0
00227  *
00228  * \param container Container to operate upon.
00229  * \param node Container node linking object to.
00230  *
00231  * \return Nothing
00232  */
00233 typedef void (*ao2_link_node_stat_fn)(struct ao2_container *container, struct ao2_container_node *node);
00234 
00235 /*!
00236  * \internal
00237  * \brief Decrement the container linked object statistic.
00238  * \since 12.4.0
00239  *
00240  * \param container Container to operate upon.
00241  * \param node Container node unlinking object from.
00242  *
00243  * \return Nothing
00244  */
00245 typedef void (*ao2_unlink_node_stat_fn)(struct ao2_container *container, struct ao2_container_node *node);
00246 
00247 /*! Container virtual methods template. */
00248 struct ao2_container_methods {
00249    /*! Destroy this container. */
00250    ao2_container_destroy_fn destroy;
00251    /*! \brief Create an empty copy of this container. */
00252    ao2_container_alloc_empty_clone_fn alloc_empty_clone;
00253    /*! \brief Create an empty copy of this container. (Debug version) */
00254    ao2_container_alloc_empty_clone_debug_fn alloc_empty_clone_debug;
00255    /*! Create a new container node. */
00256    ao2_container_new_node_fn new_node;
00257    /*! Insert a node into this container. */
00258    ao2_container_insert_fn insert;
00259    /*! Traverse the container, find the first node. */
00260    ao2_container_find_first_fn traverse_first;
00261    /*! Traverse the container, find the next node. */
00262    ao2_container_find_next_fn traverse_next;
00263    /*! Traverse the container, cleanup state. */
00264    ao2_container_find_cleanup_fn traverse_cleanup;
00265    /*! Find the next iteration element in the container. */
00266    ao2_iterator_next_fn iterator_next;
00267 #if defined(AO2_DEBUG)
00268    /*! Increment the container linked object statistic. */
00269    ao2_link_node_stat_fn link_stat;
00270    /*! Deccrement the container linked object statistic. */
00271    ao2_unlink_node_stat_fn unlink_stat;
00272    /*! Display container contents. (Method for debug purposes) */
00273    ao2_container_display dump;
00274    /*! Display container debug statistics. (Method for debug purposes) */
00275    ao2_container_statistics stats;
00276    /*! Perform an integrity check on the container. (Method for debug purposes) */
00277    ao2_container_integrity integrity;
00278 #endif   /* defined(AO2_DEBUG) */
00279 };
00280 
00281 /*!
00282  * \brief Generic container type.
00283  *
00284  * \details This is the base container type that contains values
00285  * common to all container types.
00286  *
00287  * \todo Linking and unlinking container objects is typically
00288  * expensive, as it involves a malloc()/free() of a small object
00289  * which is very inefficient.  To optimize this, we can allocate
00290  * larger arrays of container nodes when we run out of them, and
00291  * then manage our own freelist.  This will be more efficient as
00292  * we can do the freelist management while we hold the lock
00293  * (that we need anyway).
00294  */
00295 struct ao2_container {
00296    /*! Container virtual method table. */
00297    const struct ao2_container_methods *v_table;
00298    /*! Container sort function if the container is sorted. */
00299    ao2_sort_fn *sort_fn;
00300    /*! Container traversal matching function for ao2_find. */
00301    ao2_callback_fn *cmp_fn;
00302    /*! The container option flags */
00303    uint32_t options;
00304    /*! Number of elements in the container. */
00305    int elements;
00306 #if defined(AO2_DEBUG)
00307    /*! Number of nodes in the container. */
00308    int nodes;
00309    /*! Maximum number of empty nodes in the container. (nodes - elements) */
00310    int max_empty_nodes;
00311 #endif   /* defined(AO2_DEBUG) */
00312    /*!
00313     * \brief TRUE if the container is being destroyed.
00314     *
00315     * \note The destruction traversal should override any requested
00316     * search order to do the most efficient order for destruction.
00317     *
00318     * \note There should not be any empty nodes in the container
00319     * during destruction.  If there are then an error needs to be
00320     * issued about container node reference leaks.
00321     */
00322    unsigned int destroying:1;
00323 };
00324 
00325 /*!
00326  * \internal
00327  * \brief Unlink a node from this container.
00328  *
00329  * \param node Node to operate upon.
00330  * \param flags ao2_unlink_node_flags governing behavior.
00331  *
00332  * \retval 0 on errors.
00333  * \retval 1 on success.
00334  */
00335 int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flags,
00336    const char *tag, const char *file, int line, const char *func);
00337 
00338 #define __container_unlink_node(node, flags) \
00339    __container_unlink_node_debug(node, flags, NULL, NULL, 0, NULL)
00340 
00341 void container_destruct(void *_c);
00342 void container_destruct_debug(void *_c);
00343 int container_init(void);
00344 
00345 #endif /* ASTOBJ2_CONTAINER_PRIVATE_H_ */

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