aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_queue.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-05-21 06:56:21 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-05-21 06:56:21 +0000
commit2e1272adc5fe6348363276571b78b49cea4a18b5 (patch)
treeb0157454f3f78d70e42383ef9fa58a7734b1211e /apps/app_queue.c
parent464272c769fbea8842da8825f1000e4dc96f9440 (diff)
I know we have talked about rewriting app_queue for Asterisk 1.6, but once I
saw this, I couldn't help myself from changing it. Previously, for *every* device state change, app_queue would spawn a thread to handle it. Now, the device state callback just puts the state change in a queue and it gets handled by a single state change processing thread. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@65298 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_queue.c')
-rw-r--r--apps/app_queue.c77
1 files changed, 64 insertions, 13 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 63722a674..5e7e34dee 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -533,14 +533,14 @@ static enum queue_member_status get_member_status(struct call_queue *q, int max_
}
struct statechange {
+ AST_LIST_ENTRY(statechange) entry;
int state;
char dev[0];
};
-static void *changethread(void *data)
+static void *handle_statechange(struct statechange *sc)
{
struct call_queue *q;
- struct statechange *sc = data;
struct member *cur;
struct member_interface *curint;
char *loc;
@@ -618,26 +618,62 @@ static void *changethread(void *data)
return NULL;
}
-static int statechange_queue(const char *dev, enum ast_device_state state, void *ign)
+/*!
+ * \brief Data used by the device state thread
+ */
+static struct {
+ /*! Set to 1 to stop the thread */
+ unsigned int stop:1;
+ /*! The device state monitoring thread */
+ pthread_t thread;
+ /*! Lock for the state change queue */
+ ast_mutex_t lock;
+ /*! Condition for the state change queue */
+ ast_cond_t cond;
+ /*! Queue of state changes */
+ AST_LIST_HEAD_NOLOCK(, statechange) state_change_q;
+} device_state = {
+ .thread = AST_PTHREADT_NULL,
+};
+
+static void *device_state_thread(void *data)
+{
+ struct statechange *sc;
+
+ while (!device_state.stop) {
+ ast_mutex_lock(&device_state.lock);
+ while (!(sc = AST_LIST_REMOVE_HEAD(&device_state.state_change_q, entry)))
+ ast_cond_wait(&device_state.cond, &device_state.lock);
+ ast_mutex_unlock(&device_state.lock);
+
+ /* Check to see if we were woken up to see the request to stop */
+ if (device_state.stop)
+ return NULL;
+
+ handle_statechange(sc);
+
+ free(sc);
+ }
+
+ return NULL;
+}
+
+static int statechange_queue(const char *dev, enum ast_device_state state, void *data)
{
/* Avoid potential for deadlocks by spawning a new thread to handle
the event */
struct statechange *sc;
- pthread_t t;
- pthread_attr_t attr;
if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
return 0;
sc->state = state;
strcpy(sc->dev, dev);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (ast_pthread_create_background(&t, &attr, changethread, sc)) {
- ast_log(LOG_WARNING, "Failed to create update thread!\n");
- free(sc);
- }
- pthread_attr_destroy(&attr);
+
+ ast_mutex_lock(&device_state.lock);
+ AST_LIST_INSERT_TAIL(&device_state.state_change_q, sc, entry);
+ ast_cond_signal(&device_state.cond);
+ ast_mutex_unlock(&device_state.lock);
return 0;
}
@@ -4686,6 +4722,14 @@ static int unload_module(void)
{
int res;
+ if (device_state.thread != AST_PTHREADT_NULL) {
+ device_state.stop = 1;
+ ast_mutex_lock(&device_state.lock);
+ ast_cond_signal(&device_state.cond);
+ ast_mutex_unlock(&device_state.lock);
+ pthread_join(device_state.thread, NULL);
+ }
+
ast_cli_unregister_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
res = ast_manager_unregister("QueueStatus");
res |= ast_manager_unregister("Queues");
@@ -4717,10 +4761,17 @@ static int unload_module(void)
static int load_module(void)
{
int res;
- if(!reload_queues())
+
+ if (!reload_queues())
return AST_MODULE_LOAD_DECLINE;
+
if (queue_persistent_members)
reload_queue_members();
+
+ ast_mutex_init(&device_state.lock);
+ ast_cond_init(&device_state.cond, NULL);
+ ast_pthread_create(&device_state.thread, NULL, device_state_thread, NULL);
+
ast_cli_register_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
res = ast_register_application(app, queue_exec, synopsis, descrip);
res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip);