[svn-commits] rizzo: branch rizzo/astobj2 r45894 - /team/rizzo/astobj2/main/astobj2.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Sun Oct 22 12:58:50 MST 2006


Author: rizzo
Date: Sun Oct 22 14:58:49 2006
New Revision: 45894

URL: http://svn.digium.com/view/asterisk?rev=45894&view=rev
Log:
more debugging...


Modified:
    team/rizzo/astobj2/main/astobj2.c

Modified: team/rizzo/astobj2/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/main/astobj2.c?rev=45894&r1=45893&r2=45894&view=diff
==============================================================================
--- team/rizzo/astobj2/main/astobj2.c (original)
+++ team/rizzo/astobj2/main/astobj2.c Sun Oct 22 14:58:49 2006
@@ -63,30 +63,30 @@
  */
 #define EXTERNAL_OBJ(_p)	((_p) == NULL ? NULL : (_p)->user_data)
 
-int astobj2_lock(void *a)
-{
-	return ast_mutex_lock( &INTERNAL_OBJ(a)->priv_data.lock );
-}
-
-int astobj2_unlock(void *a)
-{
-	return ast_mutex_unlock( &INTERNAL_OBJ(a)->priv_data.lock );
-}
-
-/*
- * we expect a to be non-NULL
- */
-int astobj2_ref(void *a, const int delta)
+int astobj2_lock(void *user_data)
+{
+	return ast_mutex_lock( &INTERNAL_OBJ(user_data)->priv_data.lock );
+}
+
+int astobj2_unlock(void *user_data)
+{
+	return ast_mutex_unlock( &INTERNAL_OBJ(user_data)->priv_data.lock );
+}
+
+/*
+ * The argument is a pointer to the user portion.
+ */
+int astobj2_ref(void *user_data, const int delta)
 {
 #if 0
  	ast_log(LOG_NOTICE, "Reference counter changed by %i\n", delta);
 #endif
-	struct astobj2 *obj = INTERNAL_OBJ(a);
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
 
 	int current_value;
 	int ret;
 
-	assert(a != NULL);
+	assert(user_data != NULL);
 	/* if delta is 0, just return the refcount */
 	if (delta == 0)
 		return (obj->priv_data.ref_counter);
@@ -94,19 +94,19 @@
 	/* we modify with an atomic operation the reference counter */
 	ret = ast_atomic_fetchadd_int( &obj->priv_data.ref_counter, delta );
 	current_value = ret + delta;
- 	ast_log(LOG_NOTICE, "+++ refcount %d for %p\n", current_value, a);
+ 	ast_log(LOG_NOTICE, "+++ refcount %d for %p\n", current_value, user_data);
 
 	/* this case must never happen */
 	if (current_value < 0) {
-		ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, a);
+		ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
 		sleep(1);
 	}
 
 	if (current_value <= 0) { /* last reference, destroy the object */
-		ast_log(LOG_DEBUG, "refcount %d on object %p, we destroy the object\n", current_value, a);
+		ast_log(LOG_DEBUG, "refcount %d on object %p, we destroy the object\n", current_value, user_data);
 
 		if (obj->priv_data.destructor_fn != NULL) 
-			obj->priv_data.destructor_fn(a);
+			obj->priv_data.destructor_fn(user_data);
 
 		ast_mutex_destroy(&obj->priv_data.lock);
 		/* for safety, zero-out the astobj2 header and also the
@@ -127,23 +127,23 @@
 void *astobj2_obj_alloc(size_t data_size, astobj2_destructor_fn destructor_fn)
 {
 	/* allocation */
-	struct astobj2 *a;
+	struct astobj2 *obj;
 
 	if (data_size < sizeof(void *))
 		data_size = sizeof(void *);
 
-	a = ast_calloc( 1, sizeof(struct astobj2) + data_size );
-
-	if ( a == NULL)
+	obj = ast_calloc( 1, sizeof(struct astobj2) + data_size );
+
+	if (obj == NULL)
 		return NULL;
 
 	/* init */
-	ast_mutex_init(&a->priv_data.lock);
-	a->priv_data.ref_counter = 1;
-	a->priv_data.destructor_fn = destructor_fn;	/* can be NULL */
+	ast_mutex_init(&obj->priv_data.lock);
+	obj->priv_data.ref_counter = 1;
+	obj->priv_data.destructor_fn = destructor_fn;	/* can be NULL */
 
 	/* return a pointer to the user data */
-	return EXTERNAL_OBJ(a);
+	return EXTERNAL_OBJ(obj);
 }
 
 /* internal callback to destroy a container. */
@@ -167,10 +167,11 @@
  * This is basically used when we want to have a container that is
  * a simple linked list.
  */
-static int hash_zero(const void *obj, const int flags)
+static int hash_zero(const void *user_obj, const int flags)
 {
 	return 0;
 }
+
 /*
  * A container is just an object, after all!
  */
@@ -196,7 +197,9 @@
 	return c;
 }
 
-/* XXX better to keep a global count of elements */
+/*!
+ * return the number of elements in the container
+ */
 int astobj2_container_count(struct container *c)
 {
 	return c->elements;
@@ -208,14 +211,14 @@
  * XXX this should be private to the container code
  */
 struct bucket_list {
-        struct bucket_list *next;       /* pointer to next bucket_list */
-        struct astobj2 *obj;                    /* pointer to internal data */
+	struct bucket_list *next;	/* pointer to next bucket_list */
+	struct astobj2 *astobj;		/* pointer to internal data */
 }; 
 
 /*!
  * link an object to a container
  */
-void *astobj2_link(struct container *c, void *obj)
+void *astobj2_link(struct container *c, void *user_data)
 {
 	int i;
 	/* create a new list entry */
@@ -224,13 +227,13 @@
 	if (p == NULL)		/* alloc failure, die */
 		return NULL;
 	/* apply the hash function */
-	i = c->hash_fn(obj, OBJ_POINTER);
+	i = c->hash_fn(user_data, OBJ_POINTER);
 
 	astobj2_lock(c);
 	i %= c->n_buckets;
 
 	p->next = NULL;
-	p->obj = INTERNAL_OBJ(obj);
+	p->astobj = INTERNAL_OBJ(user_data);
 	if (c->buckets[i].head == NULL)
 		c->buckets[i].head = p;
 	else
@@ -244,23 +247,27 @@
 /*
  * another convenience function is a callback that matches on address
  */
-static int match_by_addr(void *obj, void *arg, int flags)
-{
-	return (obj == arg) ? CMP_MATCH | CMP_STOP : 0;
+static int match_by_addr(void *user_data, void *arg, int flags)
+{
+	int i = (user_data == arg) ? CMP_MATCH | CMP_STOP : 0;
+	// ast_verbose("match_by_addr u %p arg %p ret %d\n", user_data, arg, i);
+	return i;
 }
 
 /*! 
- * \brief Unlink an object from the list
+ * \brief Unlink an object from the container
  * and destroy the associated * astobj2_bucket_list structure.
  */
-void *astobj2_unlink(struct container *c, void *arg)
-{
-	astobj2_callback(c, OBJ_SINGLE | OBJ_UNLINK | OBJ_POINTER, match_by_addr, arg);
+void *astobj2_unlink(struct container *c, void *user_data)
+{
+	// ast_verbose("unlinking %p from container\n", user_data);
+	astobj2_callback(c, OBJ_SINGLE | OBJ_UNLINK | OBJ_POINTER, match_by_addr, user_data);
+	astobj2_ref(user_data, -1);
 	return NULL;
 }
 
 /* special callback that matches all */
-static int cb_true(void *obj, void *arg, int flags)
+static int cb_true(void *user_data, void *arg, int flags)
 {
 	return CMP_MATCH;
 }
@@ -274,8 +281,8 @@
 	const enum search_flags flags,
 	astobj2_callback_fn cb_fn, void *arg)
 {
-	int i, last;
-	struct astobj2 *ret = NULL;
+	int i, last;	/* search boundaries */
+	void *ret = NULL;
 
 	if ( (flags & (OBJ_SINGLE | OBJ_DATA)) == OBJ_DATA) {
 		ast_log(LOG_WARNING, "multiple data return not implemented yet");
@@ -298,6 +305,7 @@
 	else			/* don't know, let's scan all buckets */
 		i = -1;		/* XXX this must be fixed later. */
 
+	// ast_verbose("-- callback flags %x hash at %d\n", flags, i);
 	/* determine the search boundaries: i..last-1 */
 	if (i < 0) {
 		i = 0;
@@ -309,35 +317,41 @@
 	astobj2_lock(c);	/* avoid modifications to the content */
 
 	for(; i < last ; i++) {
+		/* scan the list with prev-cur pointers */
 		struct bucket_list *prev = NULL, *cur = c->buckets[i].head;
+
 		while (cur) {
-			int match = cb_fn(EXTERNAL_OBJ(cur->obj), arg, flags );
+			int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
 
 			/* we found the object, performing operations according flags */
 			if (match == 0) {	/* no match, no stop, continue */
 				prev = cur;
 				cur = cur->next;
 				continue;
-			} else if (match == CMP_STOP) {	/* we are done */
+			} else if (match == CMP_STOP) {	/* no match but stop, we are done */
 				i = last;
 				break;
 			}
-			/* we know CMP_MATCH is set here */
-			if (flags & OBJ_DATA)	/* must return the object, mark the value */
-				ret = cur->obj;
+			/* we have a match (CMP_MATCH) here */
+			if (flags & OBJ_DATA)	/* if must return the object, record the value */
+				ret = EXTERNAL_OBJ(cur->astobj);
+
 			if (flags & OBJ_UNLINK) {	/* must unlink */
 				struct bucket_list *x = cur;
 
+				// ast_verbose("++ unlink u %p at %p\n", EXTERNAL_OBJ(cur->astobj), cur);
 				if (prev == NULL)	/* gone from head */
 					c->buckets[i].head  = cur->next;
 				else			/* gone from the middle */
 					prev->next = cur->next;
-				/* update tail if needed needed */
-				if (c->buckets[i].tail == cur)
+				if (c->buckets[i].tail == cur) /* update tail if needed */
 					c->buckets[i].tail = prev;
-				cur = cur->next ;
-				free(x);
+				cur = cur->next ;	/* prepare for next cycle */
+				free(x);	/* free the link record */
 				ast_atomic_fetchadd_int(&c->elements, -1);
+			} else {	/* prepare for next cycle */
+				prev = cur;
+				cur = cur->next;
 			}
 
 			if ((match & CMP_STOP) || (flags & OBJ_SINGLE)) {
@@ -348,41 +362,29 @@
 			if (flags & OBJ_DATA) {
 #if 0	/* XXX to be completed */
 				/* here build a list of object pointers and increase
-				 * the reference counter for each reference created */
-				struct astobj2_list *new_obj;
-				new_obj = ast_calloc(1, sizeof(struct astobj2_list));
-				if ( new_obj == NULL ) {
-					ast_log(LOG_WARNING, "No list created, out of memory\n");
-					continue;
-				}
-				astobj2_ref(EXTERNAL_OBJ(list_pointer->obj), 1);
-				new_obj->next = (struct astobj2_list *)ret;
-				ret = new_obj;
+				 * the reference counter for each reference created
+				 */
 #endif
 			}
-			prev = cur;
-			cur = cur->next;
 		}
 	}
 	astobj2_unlock(c);
 
 	/* increase the reference counter, unlock the container and return */
-	if ( ret != NULL ) {
+	if ( ret != NULL )
 		astobj2_ref(ret, 1);
-		ret = (void *)EXTERNAL_OBJ(ret);
-	} 
 	return ret;
 }
 
 /*!
  * the find function just invokes the default callback with some reasonable flags.
  */
-void *astobj2_find(struct container *c, void *p, enum search_flags flags)
+void *astobj2_find(struct container *c, void *arg, enum search_flags flags)
 {
 	if (flags == 0)
 		flags = OBJ_SINGLE | OBJ_DATA;	/* reasonable default */
 	ast_log(LOG_NOTICE, "astobj2_find\n");
-	return astobj2_callback(c, flags, c->cmp_fn, p);
+	return astobj2_callback(c, flags, c->cmp_fn, arg);
 }
 
 /*!
@@ -429,7 +431,7 @@
 
 		if (a->pos == -1) {	/* found at the beginning of the bucket */
 			a->pos = 0;
-			a->cur = p->obj;
+			a->cur = p->astobj;
 			break;
 		}
 
@@ -439,7 +441,7 @@
 		 * The next element to return will be cand->next.
 		 */
 		for (i = 0; p; i++, p = p->next) {
-			if (p->obj == a->cur) {	/* found current element */
+			if (p->astobj == a->cur) {	/* found current element */
 				a->pos = i;	/* mark new position */
 				cand = p;
 				break;
@@ -451,7 +453,7 @@
 			continue;
 		/* ok, what we want is at cand->next */
 		a->pos++;
-		a->cur = cand->next->obj;
+		a->cur = cand->next->astobj;
 		break;
 	}
 
@@ -528,25 +530,25 @@
 		sprintf(obj, "-- this is obj %d --", i);
 		astobj2_link(c1, obj);
 	}
-	ast_cli(fd, "testing callbacks");
-	astobj2_callback(c1, 0, print_cb, (void*)fd);
-
-	ast_cli(fd, "testing iterators, remove every second object");
+	ast_cli(fd, "testing callbacks\n");
+	astobj2_callback(c1, 0, print_cb, (void *)fd);
+
+	ast_cli(fd, "testing iterators, remove every second object\n");
 	astobj2_iterator_init(c1, &ai);
 {
 	int x = 0;
 	while ( (obj = astobj2_iterator_next(&ai)) ) {
-		ast_cli(fd, "iterator on <%s>", obj);
+		ast_cli(fd, "iterator on <%s>\n", obj);
 		if (x++ & 1) {
 		    astobj2_unlink(c1, obj);
-		    astobj2_ref(obj, -1);
 		}
 	}
 }
-	ast_cli(fd, "testing callbacks again");
+	ast_cli(fd, "testing callbacks again\n");
 	astobj2_callback(c1, 0, print_cb, (void*)fd);
 
-	astobj2_ref(c1, -1);	/* destroy all */
+	ast_cli(fd, "destroy container\n");
+	astobj2_ref(c1, -1);	/* destroy container */
 	return 0;
 }
 



More information about the svn-commits mailing list