[asterisk-commits] russell: branch russell/events r65572 - in /team/russell/events: include/aste...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue May 22 19:13:06 MST 2007


Author: russell
Date: Tue May 22 21:13:06 2007
New Revision: 65572

URL: http://svn.digium.com/view/asterisk?view=rev&rev=65572
Log:
Finish the basic conversion of device state handling to the common event system.
I am still not terribly excited with how the device state events are generated
in the first place, but it is still a relic of the original code.  Device state
providers queue an event to say that the state of a device has changed.  Then,
another thread calls the device state providers callback to determine what the
new state actually is.  I really don't see why the initial event to say that
the state of a device has changed doesn't just include the new state in the
first place.  But, it's going to take a lot of work to change it ...

Modified:
    team/russell/events/include/asterisk/pbx.h
    team/russell/events/main/devicestate.c
    team/russell/events/main/pbx.c

Modified: team/russell/events/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/pbx.h?view=diff&rev=65572&r1=65571&r2=65572
==============================================================================
--- team/russell/events/include/asterisk/pbx.h (original)
+++ team/russell/events/include/asterisk/pbx.h Tue May 22 21:13:06 2007
@@ -877,8 +877,6 @@
  */
 int ast_func_write(struct ast_channel *chan, const char *function, const char *value);
 
-void ast_hint_state_changed(const char *device);
-
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/russell/events/main/devicestate.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/main/devicestate.c?view=diff&rev=65572&r1=65571&r2=65572
==============================================================================
--- team/russell/events/main/devicestate.c (original)
+++ team/russell/events/main/devicestate.c Tue May 22 21:13:06 2007
@@ -393,9 +393,6 @@
 	ast_event_queue_and_cache(event,
 		AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
 		AST_EVENT_IE_END);
-
-	/*! \todo Convert hints to be device state subscribers. */
-	ast_hint_state_changed(device);
 }
 
 static int __ast_device_state_changed_literal(char *buf)

Modified: team/russell/events/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/main/pbx.c?view=diff&rev=65572&r1=65571&r2=65572
==============================================================================
--- team/russell/events/main/pbx.c (original)
+++ team/russell/events/main/pbx.c Tue May 22 21:13:06 2007
@@ -219,6 +219,29 @@
 	{ AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
 	{ AST_EXTENSION_ONHOLD,                        "Hold" },
 	{ AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
+};
+
+struct statechange {
+	AST_LIST_ENTRY(statechange) entry;
+	char dev[0];
+};
+
+/*!
+ * \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 int pbx_builtin_answer(struct ast_channel *, void *);
@@ -1921,7 +1944,7 @@
 	return ast_extension_state2(e);    		/* Check all devices in the hint */
 }
 
-void ast_hint_state_changed(const char *device)
+static void handle_statechange(const char *device)
 {
 	struct ast_hint *hint;
 
@@ -1962,6 +1985,47 @@
 	}
 
 	AST_RWLIST_UNLOCK(&hints);
+}
+
+static int statechange_queue(const char *dev)
+{
+	/* Avoid potential for deadlocks by spawning a new thread to handle
+	   the event */
+	struct statechange *sc;
+
+	if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(dev) + 1)))
+		return 0;
+
+	strcpy(sc->dev, dev);
+
+	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;
+}
+
+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->dev);
+
+		free(sc);
+	}
+
+	return NULL;
 }
 
 /*! \brief  ast_extension_state_add: Add watcher for extension states */
@@ -6056,18 +6120,15 @@
 
 static void device_state_cb(const struct ast_event *event, void *unused)
 {
-	enum ast_device_state state;
 	const char *device;
 
-	state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
 	device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
-
 	if (ast_strlen_zero(device)) {
 		ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
 		return;
 	}
 
-	// XXX statechange_queue(device, state);
+	statechange_queue(device);
 }
 
 int load_pbx(void)
@@ -6093,6 +6154,10 @@
 	
 	/* Register manager application */
 	ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
+
+	ast_mutex_init(&device_state.lock);
+	ast_cond_init(&device_state.cond, NULL);
+	ast_pthread_create(&device_state.thread, NULL, device_state_thread, NULL);
 
 	if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL,
 			AST_EVENT_IE_END))) {



More information about the asterisk-commits mailing list