[svn-commits] file: branch file/bridging r126220 - in /team/file/bridging: bridges/ include...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Jun 28 12:31:57 CDT 2008


Author: file
Date: Sat Jun 28 12:31:56 2008
New Revision: 126220

URL: http://svn.digium.com/view/asterisk?view=rev&rev=126220
Log:
Use a dynamic array in the bridge for keeping track of channels that we need to wait on.

Modified:
    team/file/bridging/bridges/bridge_softmix.c
    team/file/bridging/include/asterisk/bridging.h
    team/file/bridging/main/bridging.c

Modified: team/file/bridging/bridges/bridge_softmix.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/bridges/bridge_softmix.c?view=diff&rev=126220&r1=126219&r2=126220
==============================================================================
--- team/file/bridging/bridges/bridge_softmix.c (original)
+++ team/file/bridging/bridges/bridge_softmix.c Sat Jun 28 12:31:56 2008
@@ -164,7 +164,7 @@
 	ast_cond_init(&cond, NULL);
 	ast_mutex_init(&lock);
 
-	while (!bridge->stop && !bridge->refresh) {
+	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
 		struct ast_bridge_channel *bridge_channel = NULL;
 		short buf[SOFTMIX_SAMPLES] = {0, };
 		struct timeval next_wakeup;

Modified: team/file/bridging/include/asterisk/bridging.h
URL: http://svn.digium.com/view/asterisk/team/file/bridging/include/asterisk/bridging.h?view=diff&rev=126220&r1=126219&r2=126220
==============================================================================
--- team/file/bridging/include/asterisk/bridging.h (original)
+++ team/file/bridging/include/asterisk/bridging.h Sat Jun 28 12:31:56 2008
@@ -254,8 +254,8 @@
 struct ast_bridge {
 	/*! Number of channels participating in the bridge */
 	int num;
-	/*! Bit to indicate that the bridge thread should examine the bridge */
-	unsigned int rebuild:1;
+	/*! Bit to indicate that the bridge thread is waiting on channels in the bridge array */
+	unsigned int waiting:1;
 	/*! Bit to indicate the bridge thread should stop */
 	unsigned int stop:1;
 	/*! Bit to indicate the bridge thread should refresh itself */
@@ -270,6 +270,12 @@
 	pthread_t thread;
 	/*! Enabled features information */
 	struct ast_bridge_features features;
+	/*! Array of channels that the bridge thread is currently handling */
+	struct ast_channel **array;
+	/*! Number of channels in the above array */
+	size_t array_num;
+	/*! Number of channels the array can handle */
+	size_t array_size;
 	/*! Linked list of channels participating in the bridge */
 	AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) channels;
 };

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=126220&r1=126219&r2=126220
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Sat Jun 28 12:31:56 2008
@@ -46,6 +46,12 @@
 /* Maximum length of a DTMF feature string */
 #define MAXIMUM_DTMF_FEATURE_STRING 8
 
+/* Initial starting point for the bridge array of channels */
+#define BRIDGE_ARRAY_START 128
+
+/* Grow rate of bridge array of channels */
+#define BRIDGE_ARRAY_GROW 32
+
 /*! Default DTMF keys for built in features */
 static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING];
 
@@ -122,16 +128,63 @@
 	return 0;
 }
 
-/*! \brief Helper function to tell the bridge thread to rebuild the bridge it is handling */
-static void bridge_rebuild(struct ast_bridge *bridge)
-{
-	/* Just set a bit to tell the bridge to rebuild, easy as pie */
-	bridge->rebuild = 1;
-
+/*! \brief Helper function to poke the bridge thread */
+static void bridge_poke(struct ast_bridge *bridge)
+{
 	/* Poke the thread just in case */
-	if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP)
+	if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) {
 		pthread_kill(bridge->thread, SIGURG);
+	}
 	
+	return;
+}
+
+/*! \brief Helper function to add a channel to the bridge array */
+static void bridge_array_add(struct ast_bridge *bridge, struct ast_channel *chan)
+{
+	/* We have to make sure the bridge thread is not using the bridge array before messing with it */
+	while (bridge->waiting) {
+		bridge_poke(bridge);
+		usleep(1);
+	}
+
+	bridge->array[bridge->array_num++] = chan;
+
+	ast_debug(1, "Added channel %p to bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num);
+
+	/* If the next addition of a channel will exceed our array size grow it out */
+	if (bridge->array_num == bridge->array_size) {
+		struct ast_channel **tmp;
+		ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW);
+		tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel*));
+		bridge->array = tmp;
+		bridge->array_size += BRIDGE_ARRAY_GROW;
+	}
+
+	return;
+}
+
+/*! \brief Helper function to remove a channel from the bridge array */
+static void bridge_array_remove(struct ast_bridge *bridge, struct ast_channel *chan)
+{
+	int i;
+
+	/* We have to make sure the bridge thread is not using the bridge array before messing with it */
+	while (bridge->waiting) {
+		bridge_poke(bridge);
+		usleep(1);
+	}
+
+	for (i = 0; i < bridge->array_num; i++) {
+		if (bridge->array[i] == chan) {
+			bridge->array[i] = (bridge->array[(bridge->array_num-1)] != chan ? bridge->array[(bridge->array_num-1)] : NULL);
+			bridge->array[(bridge->array_num-1)] = NULL;
+			bridge->array_num--;
+			ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num);
+			break;
+		}
+	}
+
 	return;
 }
 
@@ -185,7 +238,6 @@
 			ast_frfree(frame);
 			frame = NULL;
 			bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE);
-			bridge_rebuild(bridge);
 			break;
 		}
 	}
@@ -232,7 +284,7 @@
 	}
 
 	/* If all else fails just poke the bridge */
-	if (bridge->technology->poke) {
+	if (bridge->technology->poke && bridge_channel) {
 		bridge->technology->poke(bridge, bridge_channel);
 		return;
 	}
@@ -243,35 +295,22 @@
 /*! \brief Generic thread loop, TODO: Rethink this/improve it */
 static int generic_thread_loop(struct ast_bridge *bridge)
 {
-	struct ast_channel *cs[128] = { NULL, }, *winner = NULL;
-	int to = -1, count = 0;
-
-	while (!bridge->stop && !bridge->refresh) {
-		/* If told to rebuild do so */
-		if (bridge->rebuild) {
-			struct ast_bridge_channel *bridge_channel = NULL;
-			int i = 0;
-
-			/* Go through looking for channels that we should monitor */
-			AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-				if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT && !bridge_channel->suspended) {
-					cs[i++] = bridge_channel->chan;
-				}
-			}
-
-			bridge->rebuild = 0;
-
-			/* If no channels exist simply stop the thread, it will get started at a later time */
-			if (!(count = i)) {
-				break;
-			}
-		} else if (count >= 2) {
-			/* Move channels around for priority reasons */
+	while (!bridge->stop && !bridge->refresh && bridge->array_num) {
+		struct ast_channel *winner = NULL;
+		int to = -1;
+
+		/* Move channels around for priority reasons if we have more than one channel in our array */
+		if (bridge->array_num > 1) {
+			struct ast_channel *first = bridge->array[0];
+			memmove(bridge->array, bridge->array + 1, sizeof(bridge->array) - 1);
+			bridge->array[(bridge->array_num-1)] = first;
 		}
 
 		/* Wait on the channels */
 		ao2_unlock(bridge);
-		winner = ast_waitfor_n(cs, count, &to);
+		bridge->waiting = 1;
+		winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
+		bridge->waiting = 0;
 		ao2_lock(bridge);
 
 		/* Process whatever they did */
@@ -292,7 +331,7 @@
 	ast_debug(1, "Started bridge thread for %p\n", bridge);
 
 	/* Loop around until we are told to stop */
-	while (!bridge->stop) {
+	while (!bridge->stop && bridge->array_num) {
 		/* In case the refresh bit was set simply set it back to off */
 		bridge->refresh = 0;
 
@@ -371,6 +410,9 @@
 	/* Last but not least clean up the features configuration */
 	ast_bridge_features_cleanup(&bridge->features);
 
+	/* Drop the array of channels */
+	ast_free(bridge->array);
+
 	return;
 }
 
@@ -395,6 +437,10 @@
 
 	bridge->technology = bridge_technology;
 	bridge->thread = AST_PTHREADT_NULL;
+
+	/* Create an array of pointers for the channels that will be joining us */
+	bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*));
+	bridge->array_size = BRIDGE_ARRAY_START;
 
 	ast_set_flag(&bridge->feature_flags, flags);
 
@@ -413,6 +459,10 @@
 	struct ast_bridge_channel *bridge_channel = NULL;
 
 	ao2_lock(bridge);
+
+	bridge->stop = 1;
+
+	bridge_poke(bridge);
 
 	ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge);
 
@@ -732,6 +782,8 @@
 	AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
 	bridge_channel->bridge->num++;
 
+	bridge_array_add(bridge_channel->bridge, bridge_channel->chan);
+
 	if (bridge_channel->swap) {
 		struct ast_bridge_channel *bridge_channel2 = NULL;
 
@@ -757,9 +809,6 @@
 			ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
 		}
 	}
-	
-	/* Tell the bridge to rebuild as we are joining in */
-	bridge_rebuild(bridge_channel->bridge);
 
 	/* Actually execute the respective threading model, and keep our bridge thread alive */
 	while (state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
@@ -782,9 +831,6 @@
 		}
 	}
 
-	/* Tell the bridge to rebuild as we are leaving */
-	bridge_rebuild(bridge_channel->bridge);
-
 	/* Tell the bridge technology we are leaving so they tear us down */
 	if (bridge_channel->bridge->technology->leave) {
 		ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
@@ -796,6 +842,8 @@
 	/* Remove channel from the bridge */
 	bridge_channel->bridge->num--;
 	AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry);
+
+	bridge_array_remove(bridge_channel->bridge, bridge_channel->chan);
 
 	/* Perform the smart bridge operation if needed since a channel has left */
 	if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
@@ -977,10 +1025,6 @@
 		ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
 		bridge1->thread = AST_PTHREADT_STOP;
 	}
-
-	/* Tell each bridge that something is going to happen */
-	bridge_rebuild(bridge0);
-	bridge_rebuild(bridge1);
 
 	/* Move channels from bridge1 over to bridge0 */
 	while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) {
@@ -996,11 +1040,15 @@
 		bridge1->num--;
 		ao2_ref(bridge1, -1);
 
+		bridge_array_remove(bridge1, bridge_channel->chan);
+
 		/* Now add them into the bridge they are joining, increase channel count, and bump up reference count */
 		bridge_channel->bridge = bridge0;
 		AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry);
 		bridge0->num++;
 		ao2_ref(bridge0, +1);
+
+		bridge_array_add(bridge0, bridge_channel->chan);
 
 		/* Make the channel compatible with the new bridge it is joining or else formats would go amuck */
 		bridge_make_compatible(bridge0, bridge_channel);
@@ -1039,15 +1087,11 @@
 		return -1;
 	}
 
-	bridge_rebuild(bridge);
-
 	bridge_channel->suspended = 1;
 
+	bridge_array_remove(bridge, chan);
+
 	ao2_unlock(bridge);
-
-	while (bridge->rebuild) {
-		usleep(1);
-	}
 
 	return 0;
 }
@@ -1063,9 +1107,9 @@
 		return -1;
 	}
 
-	bridge_rebuild(bridge);
-
 	bridge_channel->suspended = 0;
+
+	bridge_array_add(bridge, chan);
 
 	ao2_unlock(bridge);
 
@@ -1342,9 +1386,6 @@
 {
 	struct ast_bridge_channel *bridge_channel = NULL;
 
-	/* Trigger a rebuild now just in case */
-	bridge_rebuild(bridge);
-
 	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
 		if (bridge_channel->chan == chan)
 			continue;




More information about the svn-commits mailing list