switch_mutex_t *dtmf_mutex;
switch_mutex_t *flag_mutex;
switch_mutex_t *state_mutex;
+ switch_mutex_t *thread_mutex;
switch_mutex_t *profile_mutex;
switch_core_session_t *session;
switch_channel_state_t state;
switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);
+ switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
(*channel)->hangup_cause = SWITCH_CAUSE_NONE;
(*channel)->name = "";
return CS_DESTROY;
}
+static inline void careful_set(switch_channel_t *channel, switch_channel_state_t *state, switch_channel_state_t val) {
+
+ if (switch_mutex_trylock(channel->thread_mutex)) {
+ *state = val;
+ switch_mutex_unlock(channel->thread_mutex);
+ } else {
+ switch_mutex_t *mutex = switch_core_session_get_mutex(channel->session);
+ int x = 0;
+
+ for (x = 0; x < 100; x++) {
+ if (switch_mutex_trylock(mutex) == SWITCH_STATUS_SUCCESS) {
+ *state = val;
+ switch_mutex_unlock(mutex);
+ break;
+ } else {
+ switch_cond_next();
+ }
+ }
+
+ if (x == 100) {
+ *state = val;
+ }
+
+ }
+}
+
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state,
const char *file, const char *func, int line)
{
switch_mutex_lock(channel->state_mutex);
- channel->running_state = state;
+ careful_set(channel, &channel->running_state, state);
if (state <= CS_DESTROY) {
switch_event_t *event;
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n",
channel->name, state_names[last_state], state_names[state]);
- channel->state = state;
+ careful_set(channel, &channel->state, state);
if (state == CS_HANGUP && !channel->hangup_cause) {
channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
return channel->state;
}
+SWITCH_DECLARE(void) switch_channel_state_thread_lock(switch_channel_t *channel)
+{
+ switch_mutex_lock(channel->thread_mutex);
+}
+
+SWITCH_DECLARE(void) switch_channel_state_thread_unlock(switch_channel_t *channel)
+{
+ switch_mutex_unlock(channel->thread_mutex);
+}
+
SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event)
{
switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL;
switch_ivr_parse_all_events(session);
if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
+ switch_channel_state_thread_lock(session->channel);
switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
switch_thread_cond_wait(session->cond, session->mutex);
}
switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING);
+ switch_channel_state_thread_unlock(session->channel);
}
switch_ivr_parse_all_events(session);