[asterisk-commits] mmichelson: branch mmichelson/ao2_containers r165009 - /team/mmichelson/ao2_c...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Dec 16 17:54:37 CST 2008


Author: mmichelson
Date: Tue Dec 16 17:54:37 2008
New Revision: 165009

URL: http://svn.digium.com/view/asterisk?view=rev&rev=165009
Log:
Add some documentation to astobj2.h to indicate how
linked lists fit into the picture.

My struggles with the skiplist iterator implementation
have led me to abandon the idea of ao2 skip lists for
now and focus this branch around the implementation of
linked lists only.


Modified:
    team/mmichelson/ao2_containers/include/asterisk/astobj2.h

Modified: team/mmichelson/ao2_containers/include/asterisk/astobj2.h
URL: http://svn.digium.com/view/asterisk/team/mmichelson/ao2_containers/include/asterisk/astobj2.h?view=diff&rev=165009&r1=165008&r2=165009
==============================================================================
--- team/mmichelson/ao2_containers/include/asterisk/astobj2.h (original)
+++ team/mmichelson/ao2_containers/include/asterisk/astobj2.h Tue Dec 16 17:54:37 2008
@@ -90,7 +90,7 @@
 
     struct ao2_container *c;
 
-    c = ao2_container_alloc(MAX_BUCKETS, my_hash_fn, my_cmp_fn);
+    c = ao2_hashtable_alloc(MAX_BUCKETS, my_hash_fn, my_cmp_fn);
     \endcode
 
 where
@@ -102,6 +102,27 @@
 - my_cmp_fn() is the default comparison function used when doing
   searches on the container,
 
+If you don't wish to use a hash table (perhaps because you require
+that data is kept in the order in which it is added), then you may
+instead allocate a linked list
+
+	<b>Sample Usage:</b>
+	\code
+
+	struct ao2_container *c;
+
+	c = ao2_linkedlist_alloc(my_cmp_fn, AO2_LINKEDLIST_BACK);
+	\endcode
+
+where
+
+- my_cmp_fn() is the default comparison function used when doing
+  searches on the container
+- AO2_LINKEDLIST_BACK indicates the direction that data should be
+  added to the container. AO2_LINKEDLIST_BACK will add all subsequent
+  data to the end of the list, and AO2_LINKEDLIST_FRONT will add all
+  subsequent data to the begninning of the list.
+
 A container knows little or nothing about the objects it stores,
 other than the fact that they have been created by ao2_alloc().
 All knowledge of the (user-defined) internals of the objects
@@ -109,8 +130,9 @@
 to ao2_container_alloc().
 
 If we want to insert an object in a container, we should
-initialize its fields -- especially, those used by my_hash_fn() --
-to compute the bucket to use.
+initialize its fields, especially those used by my_hash_fn()
+for hash tables.
+
 Once done, we can link an object to a container with
 
     ao2_link(c, o);
@@ -121,15 +143,13 @@
 Linking an object to a container increases its refcount by 1
 automatically.
 
-\note While an object o is in a container, we expect that
-my_hash_fn(o) will always return the same value. The function
-does not lock the object to be computed, so modifications of
-those fields that affect the computation of the hash should
-be done by extracting the object from the container, and
-reinserting it after the change (this is not terribly expensive).
-
-\note A container with a single buckets is effectively a linked
-list. However there is no ordering among elements.
+\note For hash tables, while an object o is in a container, we 
+expect that my_hash_fn(o) will always return the same value. 
+The function does not lock the object to be computed, so 
+modifications of those fields that affect the computation of 
+the hash should be done by extracting the object from the 
+container, and reinserting it after the change (this is not 
+terribly expensive).
 
 - \ref AstObj2_Containers
 - \ref astobj2.h All documentation for functions and data structures
@@ -525,8 +545,8 @@
 	     OBJ_NODATA   - don't return the object if found (no ref count change)
 	     OBJ_MULTIPLE - don't stop at first match (not fully implemented)
 	     OBJ_POINTER  - if set, 'arg' is an object pointer, and a hashtable
-                        search will be done. If not, a traversal is done through
-                        all the hashtable 'buckets'..
+                        search will be done if the c is a hash table. If not, 
+						a traversal is done through all the hashtable 'buckets'..
       - fn is a func that returns int, and takes 3 args: 
         (void *obj, void *arg, int flags);
           obj is an object
@@ -650,22 +670,6 @@
 	void (* const destroy)(struct ao2_container *c);
 };
 
-/*! \brief
- * Allocate and initialize a container 
- * with the desired number of buckets.
- * 
- * We allocate space for a struct astobj_container, struct container
- * and the buckets[] array.
- *
- * \param n_buckets Number of buckets for hash
- * \param hash_fn Pointer to a function computing a hash value.
- * \param cmp_fn Pointer to a function comparating key-value 
- * 			with a string. (can be NULL)
- * \return A pointer to a struct container.
- *
- * destructor is set implicitly.
- */
-
 #ifdef REF_DEBUG
 #define ao2_t_container_alloc(arg1,arg2,arg3,arg4) ao2_hashtable_alloc_debug((arg1), (arg2), (arg3), (arg4),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ao2_container_alloc(arg1,arg2,arg3)        ao2_hashtable_alloc_debug((arg1), (arg2), (arg3), "",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
@@ -678,11 +682,38 @@
  * Each of these may be called in order to create a 
  * new ao2_container of the type desired
  */
+
+
+ /*! \brief
+ * Allocate and initialize a hash table 
+ * with the desired number of buckets.
+ * 
+ * We allocate space for a struct astobj_container, struct container
+ * and the buckets[] array.
+ *
+ * \note This allocation function is what is called by the macros
+ * ao2_container_alloc and ao2_t_container_alloc
+ *
+ * \param n_buckets Number of buckets for hash
+ * \param hash_fn Pointer to a function computing a hash value.
+ * \param cmp_fn Pointer to a function comparating key-value 
+ * 			with a string. (can be NULL)
+ * \return A pointer to a struct container.
+ *
+ * destructor is set implicitly.
+ */* \
 struct ao2_container *ao2_hashtable_alloc(const uint n_buckets,
 										  ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn);
 
 #define AO2_LINKEDLIST_FRONT 1
 #define AO2_LINKEDLIST_BACK 2
+/*! \brief Allocate a linked list of ao2 objects. 
+ *
+ * \param cmp_fn Comparison function used to find objects
+ * \param direction Determines where new items are added to the list.\
+ * AO2_LINKEDLIST_FRONT adds new list entries to the front of the list\
+ * AO2_LINKEDLIST_BACK adds new list entries to the back of the list
+ */
 struct ao2_container *ao2_linkedlist_alloc(ao2_callback_fn *cmp_fn, int direction);
 
 /*! \brief
@@ -879,14 +910,19 @@
  * However, within the current hash table container, the following is true:
  *  - It is not possible to miss an object in the container while iterating
  *    unless it gets added after the iteration begins and is added to a bucket
- *    that is before the one the current object is in.  In this case, even if
- *    you locked the container around the entire iteration loop, you still would
- *    not see this object, because it would still be waiting on the container
- *    lock so that it can be added.
+ *    that is before the one the current object is in.  For a linked list, which
+ *    does not have "buckets," it is possible to miss an item if it is added to a
+ *    position in the list prior to the one pointed to by the iterator (only
+ *    possible with linked lists allocated with direction AO2_LINKEDLIST_FRONT). 
+ *    In this case, even if you locked the container around the entire iteration loop, 
+ *    you still would not see this object, because it would still be waiting on 
+ *    the container lock so that it can be added.
  *  - It would be extremely rare to see an object twice.  The only way this can
  *    happen is if an object got unlinked from the container and added again 
  *    during the same iteration.  Furthermore, when the object gets added back,
- *    it has to be in the current or later bucket for it to be seen again.
+ *    it has to be in the current or later bucket for it to be seen again. The only
+ *    way that a linked list could iterate over the same item twice would be if
+ *    the list was allocated with direction AO2_LINKEDLIST_BACK.
  *
  * An iterator must be first initialized with ao2_iterator_init(),
  * then we can use o = ao2_iterator_next() to move from one
@@ -927,7 +963,7 @@
  * The iterator "points" to the current object, which is identified
  * by three values:
  *
- * - a bucket number;
+ * - a bucket number. This is not used by a linked list iterator;
  * - the object_id, which is also the container version number
  *   when the object was inserted. This identifies the object
  *   univoquely, however reaching the desired object requires
@@ -945,7 +981,7 @@
 	/*! operation flags */
 	int flags;
 #define	F_AO2I_DONTLOCK	1	/*!< don't lock when iterating */
-	/*! current bucket */
+	/*! current bucket, in the case of hash tables */
 	int bucket;
 	/*! container version */
 	uint c_version;




More information about the asterisk-commits mailing list