[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r395338 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jul 24 17:55:26 CDT 2013
Author: rmudgett
Date: Wed Jul 24 17:55:24 2013
New Revision: 395338
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395338
Log:
* Convert interval timers to use the ast_waitfor_nandfds() timeout.
* Remove bridge channel action for intervals. Now the main loop handles
running interval hooks.
Modified:
team/rmudgett/bridge_phase/include/asterisk/bridging_channel_internal.h
team/rmudgett/bridge_phase/include/asterisk/bridging_features.h
team/rmudgett/bridge_phase/main/bridging.c
team/rmudgett/bridge_phase/main/bridging_channel.c
Modified: team/rmudgett/bridge_phase/include/asterisk/bridging_channel_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging_channel_internal.h?view=diff&rev=395338&r1=395337&r2=395338
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging_channel_internal.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging_channel_internal.h Wed Jul 24 17:55:24 2013
@@ -40,8 +40,6 @@
enum bridge_channel_action_type {
/*! Bridged channel is to detect a feature hook */
BRIDGE_CHANNEL_ACTION_FEATURE,
- /*! Bridged channel is to act on an interval hook */
- BRIDGE_CHANNEL_ACTION_INTERVAL,
/*! Bridged channel is to send a DTMF stream out */
BRIDGE_CHANNEL_ACTION_DTMF_STREAM,
/*! Bridged channel is to indicate talking start */
Modified: team/rmudgett/bridge_phase/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging_features.h?view=diff&rev=395338&r1=395337&r2=395338
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging_features.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging_features.h Wed Jul 24 17:55:24 2013
@@ -226,8 +226,6 @@
struct ast_bridge_hook_timer_parms timer;
};
-#define BRIDGE_FEATURES_INTERVAL_RATE 10
-
/*!
* \brief Structure that contains features information
*/
@@ -238,8 +236,6 @@
struct ao2_container *other_hooks;
/*! Attached interval hooks */
struct ast_heap *interval_hooks;
- /*! Used to determine when interval based features should be checked */
- struct ast_timer *interval_timer;
/*! Limits feature data */
struct ast_bridge_features_limits *limits;
/*! Feature flags that are enabled */
Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=395338&r1=395337&r2=395338
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Wed Jul 24 17:55:24 2013
@@ -3641,14 +3641,6 @@
return -1;
}
- if (!features->interval_timer) {
- if (!(features->interval_timer = ast_timer_open())) {
- ast_log(LOG_ERROR, "Failed to open a timer when adding a timed bridging feature.\n");
- return -1;
- }
- ast_timer_set_rate(features->interval_timer, BRIDGE_FEATURES_INTERVAL_RATE);
- }
-
/* Allocate new hook and setup it's various variables */
hook = (struct ast_bridge_hook_timer *) bridge_hook_generic(sizeof(*hook), callback,
hook_pvt, destructor, remove_flags);
@@ -3920,11 +3912,6 @@
ao2_ref(hook, -1);
}
features->interval_hooks = ast_heap_destroy(features->interval_hooks);
- }
-
- if (features->interval_timer) {
- ast_timer_close(features->interval_timer);
- features->interval_timer = NULL;
}
/* If the features contains a limits pvt, destroy that as well. */
Modified: team/rmudgett/bridge_phase/main/bridging_channel.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging_channel.c?view=diff&rev=395338&r1=395337&r2=395338
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging_channel.c (original)
+++ team/rmudgett/bridge_phase/main/bridging_channel.c Wed Jul 24 17:55:24 2013
@@ -698,20 +698,6 @@
bridge_channel, parkee_uuid, parker_uuid, app_data);
}
-static int bridge_channel_interval_ready(struct ast_bridge_channel *bridge_channel)
-{
- struct ast_bridge_features *features = bridge_channel->features;
- struct ast_bridge_hook_timer *hook;
- int ready;
-
- ast_heap_wrlock(features->interval_hooks);
- hook = ast_heap_peek(features->interval_hooks, 1);
- ready = hook && ast_tvdiff_ms(hook->timer.trip_time, ast_tvnow()) <= 0;
- ast_heap_unlock(features->interval_hooks);
-
- return ready;
-}
-
int ast_bridge_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking)
{
struct ast_frame action = {
@@ -833,15 +819,26 @@
ast_bridge_unlock(bridge_channel->bridge);
}
-/*! \brief Internal function that activates interval hooks on a bridge channel */
-static void bridge_channel_interval(struct ast_bridge_channel *bridge_channel)
-{
+/*!
+ * \internal
+ * \brief Handle bridge channel interval expiration.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Channel to run expired intervals on.
+ *
+ * \return Nothing
+ */
+static void bridge_channel_handle_interval(struct ast_bridge_channel *bridge_channel)
+{
+ struct ast_heap *interval_hooks;
struct ast_bridge_hook_timer *hook;
struct timeval start;
-
- ast_heap_wrlock(bridge_channel->features->interval_hooks);
+ int hook_run = 0;
+
+ interval_hooks = bridge_channel->features->interval_hooks;
+ ast_heap_wrlock(interval_hooks);
start = ast_tvnow();
- while ((hook = ast_heap_peek(bridge_channel->features->interval_hooks, 1))) {
+ while ((hook = ast_heap_peek(interval_hooks, 1))) {
int interval;
unsigned int execution_time;
@@ -851,17 +848,22 @@
break;
}
ao2_ref(hook, +1);
- ast_heap_unlock(bridge_channel->features->interval_hooks);
+ ast_heap_unlock(interval_hooks);
+
+ if (!hook_run) {
+ hook_run = 1;
+ bridge_channel_suspend(bridge_channel);
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ }
ast_debug(1, "Executing hook %p on %p(%s)\n",
hook, bridge_channel, ast_channel_name(bridge_channel->chan));
interval = hook->generic.callback(bridge_channel->bridge, bridge_channel,
hook->generic.hook_pvt);
- ast_heap_wrlock(bridge_channel->features->interval_hooks);
- if (ast_heap_peek(bridge_channel->features->interval_hooks,
- hook->timer.heap_index) != hook
- || !ast_heap_remove(bridge_channel->features->interval_hooks, hook)) {
+ ast_heap_wrlock(interval_hooks);
+ if (ast_heap_peek(interval_hooks, hook->timer.heap_index) != hook
+ || !ast_heap_remove(interval_hooks, hook)) {
/* Interval hook is already removed from the bridge_channel. */
ao2_ref(hook, -1);
continue;
@@ -898,12 +900,17 @@
hook->timer.trip_time = ast_tvadd(start, ast_samp2tv(hook->timer.interval - execution_time, 1000));
hook->timer.seqno = ast_atomic_fetchadd_int((int *) &bridge_channel->features->interval_sequence, +1);
- if (ast_heap_push(bridge_channel->features->interval_hooks, hook)) {
+ if (ast_heap_push(interval_hooks, hook)) {
/* Could not push the hook back onto the heap. */
ao2_ref(hook, -1);
}
}
- ast_heap_unlock(bridge_channel->features->interval_hooks);
+ ast_heap_unlock(interval_hooks);
+
+ if (hook_run) {
+ ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+ bridge_channel_unsuspend(bridge_channel);
+ }
}
static int bridge_channel_write_dtmf_stream(struct ast_bridge_channel *bridge_channel, const char *dtmf)
@@ -1138,13 +1145,6 @@
static void bridge_channel_handle_action(struct ast_bridge_channel *bridge_channel, struct ast_frame *action)
{
switch (action->subclass.integer) {
- case BRIDGE_CHANNEL_ACTION_INTERVAL:
- bridge_channel_suspend(bridge_channel);
- ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
- bridge_channel_interval(bridge_channel);
- ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
- bridge_channel_unsuspend(bridge_channel);
- break;
case BRIDGE_CHANNEL_ACTION_FEATURE:
bridge_channel_suspend(bridge_channel);
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
@@ -1380,6 +1380,9 @@
/* Clear any BLINDTRANSFER and ATTENDEDTRANSFER since the transfer has completed. */
pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", NULL);
pbx_builtin_setvar_helper(bridge_channel->chan, "ATTENDEDTRANSFER", NULL);
+
+ /* Wake up the bridge channel thread to reevaluate any interval timers. */
+ ast_queue_frame(bridge_channel->chan, &ast_null_frame);
bridge->reconfigured = 1;
return 0;
@@ -1521,36 +1524,6 @@
ast_frfree(fr);
}
-/*!
- * \internal
- * \brief Handle bridge channel interval expiration.
- * \since 12.0.0
- *
- * \param bridge_channel Channel to check interval on.
- *
- * \return Nothing
- */
-static void bridge_channel_handle_interval(struct ast_bridge_channel *bridge_channel)
-{
- struct ast_timer *interval_timer;
-
- interval_timer = bridge_channel->features->interval_timer;
- if (interval_timer) {
- if (ast_wait_for_input(ast_timer_fd(interval_timer), 0) == 1) {
- ast_timer_ack(interval_timer, 1);
- if (bridge_channel_interval_ready(bridge_channel)) {
-/* BUGBUG since this is now only run by the channel thread, there is no need to queue the action once this intervals become a first class wait item in bridge_channel_wait(). */
- struct ast_frame interval_action = {
- .frametype = AST_FRAME_BRIDGE_ACTION,
- .subclass.integer = BRIDGE_CHANNEL_ACTION_INTERVAL,
- };
-
- ast_bridge_channel_queue_frame(bridge_channel, &interval_action);
- }
- }
- }
-}
-
/*! \brief Internal function to handle DTMF from a channel */
static struct ast_frame *bridge_handle_dtmf(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
{
@@ -1638,6 +1611,39 @@
/*!
* \internal
+ * \brief Determine how long till the next timer interval.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Channel to determine how long can wait.
+ *
+ * \retval ms Number of milliseconds to wait.
+ * \retval -1 to wait forever.
+ */
+static int bridge_channel_next_interval(struct ast_bridge_channel *bridge_channel)
+{
+ struct ast_heap *interval_hooks = bridge_channel->features->interval_hooks;
+ struct ast_bridge_hook_timer *hook;
+ int ms;
+
+ ast_heap_wrlock(interval_hooks);
+ hook = ast_heap_peek(interval_hooks, 1);
+ if (hook) {
+ ms = ast_tvdiff_ms(hook->timer.trip_time, ast_tvnow());
+ if (ms < 0) {
+ /* Expire immediately. An interval hook is ready to run. */
+ ms = 0;
+ }
+ } else {
+ /* No hook so wait forever. */
+ ms = -1;
+ }
+ ast_heap_unlock(interval_hooks);
+
+ return ms;
+}
+
+/*!
+ * \internal
* \brief Wait for something to happen on the bridge channel and handle it.
* \since 12.0.0
*
@@ -1649,7 +1655,7 @@
*/
static void bridge_channel_wait(struct ast_bridge_channel *bridge_channel)
{
- int ms = -1;
+ int ms;
int outfd;
struct ast_channel *chan;
@@ -1669,7 +1675,7 @@
bridge_channel->waiting = 1;
ast_bridge_channel_unlock(bridge_channel);
outfd = -1;
-/* BUGBUG need to make the next expiring active interval setup ms timeout rather than holding up the chan reads. */
+ ms = bridge_channel_next_interval(bridge_channel);
chan = ast_waitfor_nandfds(&bridge_channel->chan, 1,
&bridge_channel->alert_pipe[0], 1, NULL, &outfd, &ms);
bridge_channel->waiting = 0;
@@ -1686,10 +1692,12 @@
if (!bridge_channel->suspended
&& bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
if (chan) {
- bridge_channel_handle_interval(bridge_channel);
bridge_handle_trip(bridge_channel);
} else if (-1 < outfd) {
bridge_channel_handle_write(bridge_channel);
+ } else if (ms == 0) {
+ /* An interval expired. */
+ bridge_channel_handle_interval(bridge_channel);
}
}
bridge_channel->activity = AST_BRIDGE_CHANNEL_THREAD_IDLE;
More information about the asterisk-commits
mailing list