[asterisk-commits] file: branch file/bridging r126220 - in /team/file/bridging: bridges/ include...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list