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

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jun 27 22:12:14 CDT 2008


Author: file
Date: Fri Jun 27 22:12:12 2008
New Revision: 126151

URL: http://svn.digium.com/view/asterisk?view=rev&rev=126151
Log:
Bring back multithreaded mode and improve the bridge thread so that when moving between bridging technologies the new bridge thread function is called. This way the current thread is not stopped so a new one does not need to be created.

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=126151&r1=126150&r2=126151
==============================================================================
--- team/file/bridging/bridges/bridge_softmix.c (original)
+++ team/file/bridging/bridges/bridge_softmix.c Fri Jun 27 22:12:12 2008
@@ -49,6 +49,7 @@
 #include "asterisk/options.h"
 #include "asterisk/logger.h"
 #include "asterisk/slinfactory.h"
+#include "asterisk/astobj2.h"
 
 #define SOFTMIX_INTERVAL 20 /* Valid options are 10, 20, and 30 */
 #define SOFTMIX_SAMPLES (320 * (SOFTMIX_INTERVAL / 10))
@@ -163,7 +164,7 @@
 	ast_cond_init(&cond, NULL);
 	ast_mutex_init(&lock);
 
-	while (bridge->thread != AST_PTHREADT_STOP) {
+	while (!bridge->stop && !bridge->refresh) {
 		struct ast_bridge_channel *bridge_channel = NULL;
 		short buf[SOFTMIX_SAMPLES] = {0, };
 		struct timeval next_wakeup;
@@ -212,6 +213,8 @@
 			pthread_kill(bridge_channel->thread, SIGURG);
 		}
 
+		ao2_unlock(bridge);
+
 		/* If there is a skew value incorporate it into the base time to adjust for timing */
 		if (previous_skew && skew) {
 			int adjust = abs(skew-previous_skew), new_adjust = 0;
@@ -240,6 +243,8 @@
 		
 		/* Calculate a skew value (what we wanted versus what we got) */
 		skew = ast_tvdiff_ms(ast_tvnow(), next_wakeup);
+
+		ao2_lock(bridge);
 	}
 
 	ast_mutex_destroy(&lock);

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=126151&r1=126150&r2=126151
==============================================================================
--- team/file/bridging/include/asterisk/bridging.h (original)
+++ team/file/bridging/include/asterisk/bridging.h Fri Jun 27 22:12:12 2008
@@ -256,6 +256,10 @@
 	int num;
 	/*! Bit to indicate that the bridge thread should examine the bridge */
 	unsigned int rebuild:1;
+	/*! Bit to indicate the bridge thread should stop */
+	unsigned int stop:1;
+	/*! Bit to indicate the bridge thread should refresh itself */
+	unsigned int refresh:1;
 	/*! Bridge flags to tweak behavior */
 	struct ast_flags feature_flags;
 	/*! Bridge technology that is handling the bridge */

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=126151&r1=126150&r2=126151
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Fri Jun 27 22:12:12 2008
@@ -164,7 +164,7 @@
 	}
 
 	/* Since all the channels are going away let's go ahead and stop our on thread */
-	bridge->thread = AST_PTHREADT_STOP;
+	bridge->stop = 1;
 
 	return;
 }
@@ -194,7 +194,7 @@
 }
 
 /*! \brief Internal function to handle when a channel or bridge needs servicing */
-attribute_unused static void bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
+static void bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
 {
 	/* If no bridge channel has been provided and the actual channel has been provided find it */
 	if (chan && !bridge_channel)
@@ -246,9 +246,7 @@
 	struct ast_channel *cs[128] = { NULL, }, *winner = NULL;
 	int to = -1, count = 0;
 
-	ao2_lock(bridge);
-
-	while (bridge->thread != AST_PTHREADT_STOP) {
+	while (!bridge->stop && !bridge->refresh) {
 		/* If told to rebuild do so */
 		if (bridge->rebuild) {
 			struct ast_bridge_channel *bridge_channel = NULL;
@@ -280,8 +278,6 @@
 		bridge_handle_trip(bridge, NULL, winner, -1);
 	}
 
-	ao2_unlock(bridge);
-
 	return 0;
 }
 
@@ -291,15 +287,24 @@
 	struct ast_bridge *bridge = data;
 	int res = 0;
 
+	ao2_lock(bridge);
+
 	ast_debug(1, "Started bridge thread for %p\n", bridge);
 
-	/* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
-	res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge));
+	/* Loop around until we are told to stop */
+	while (!bridge->stop) {
+		/* In case the refresh bit was set simply set it back to off */
+		bridge->refresh = 0;
+
+		ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge);
+		
+		/* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
+		res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge));
+	}
 
 	ast_debug(1, "Ending bridge thread for %p\n", bridge);
 
 	/* Indicate the bridge thread is no longer active */
-	ao2_lock(bridge);
 	bridge->thread = AST_PTHREADT_NULL;
 	ao2_unlock(bridge);
 
@@ -505,9 +510,15 @@
 
 	/* If a thread is currently executing for the current technology tell it to stop */
 	if (bridge->thread != AST_PTHREADT_NULL) {
-		ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
-		pthread_kill(bridge->thread, SIGURG);
-		bridge->thread = AST_PTHREADT_STOP;
+		/* If the new bridge technology also needs a thread simply tell the bridge thread to refresh itself. This has the benefit of not incurring the cost/time of tearing down and bringing up a new thread. */
+		if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
+			ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
+			bridge->refresh = 1;
+		} else {
+			ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
+			bridge->stop = 1;
+			pthread_kill(bridge->thread, SIGURG);
+		}
 	}
 
 	/* Since we are soon going to pass this bridge to a new technology we need to NULL out the bridge_pvt pointer but don't worry as it still exists in temp_bridge, ditto for the old technology */
@@ -574,6 +585,37 @@
 /*! \brief Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve */
 static enum ast_bridge_channel_state bridge_channel_join_multithreaded(struct ast_bridge_channel *bridge_channel)
 {
+	int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
+	struct ast_channel *chan = NULL;
+
+	/* Add any file descriptors we may want to monitor */
+	if (bridge_channel->bridge->technology->fd) {
+		for (i = 0; i < 4; i ++) {
+			if (bridge_channel->fds[i] >= 0) {
+				fds[nfds++] = bridge_channel->fds[i];
+			}
+		}
+	}
+
+	ao2_unlock(bridge_channel->bridge);
+
+	/* Wait for data to either come from the channel or us to be signalled */
+	if (!bridge_channel->suspended) {
+		ast_debug(1, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
+		chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
+	} else {
+		ast_mutex_lock(&bridge_channel->lock);
+		ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
+		ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
+		ast_mutex_unlock(&bridge_channel->lock);
+	}
+
+	ao2_lock(bridge_channel->bridge);
+
+	if (!bridge_channel->suspended) {
+		bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
+	}
+
 	return bridge_channel->state;
 }
 
@@ -583,6 +625,7 @@
 	ao2_unlock(bridge_channel->bridge);
 	ast_mutex_lock(&bridge_channel->lock);
 	if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+		ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
 		ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
 	}
 	ast_mutex_unlock(&bridge_channel->lock);
@@ -689,9 +732,6 @@
 	AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
 	bridge_channel->bridge->num++;
 
-	/* Make the channel compatible with the bridge */
-	bridge_make_compatible(bridge_channel->bridge, bridge_channel);
-
 	if (bridge_channel->swap) {
 		struct ast_bridge_channel *bridge_channel2 = NULL;
 
@@ -706,6 +746,9 @@
 		/* Perform the smart bridge operation, basically see if we need to move around between technologies */
 		smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num);
 	}
+
+	/* Make the channel compatible with the bridge */
+	bridge_make_compatible(bridge_channel->bridge, bridge_channel);
 	
 	/* Tell the bridge technology we are joining so they set us up */
 	if (bridge_channel->bridge->technology->join) {
@@ -722,6 +765,7 @@
 	while (state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
 		/* If the technology requires a thread and one is not running, start it up */
 		if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
+			bridge_channel->bridge->stop = 0;
 			ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
 			ao2_ref(bridge_channel->bridge, +1);
 			if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {




More information about the svn-commits mailing list