[asterisk-commits] russell: branch russell/res_monkeys r81289 - in /team/russell/res_monkeys: ap...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Aug 28 15:33:48 CDT 2007


Author: russell
Date: Tue Aug 28 15:33:47 2007
New Revision: 81289

URL: http://svn.digium.com/view/asterisk?view=rev&rev=81289
Log:
Change func_announce to use a channel attached thread.  To do this, I updated
channel attached threads to be both stopped automatically on channel destruction
as well as able to be stopped early.  In this case, it is exposed to the dialplan
using a function.

Modified:
    team/russell/res_monkeys/apps/app_monkeys.c
    team/russell/res_monkeys/funcs/func_announce.c
    team/russell/res_monkeys/include/asterisk/channel.h
    team/russell/res_monkeys/main/channel.c

Modified: team/russell/res_monkeys/apps/app_monkeys.c
URL: http://svn.digium.com/view/asterisk/team/russell/res_monkeys/apps/app_monkeys.c?view=diff&rev=81289&r1=81288&r2=81289
==============================================================================
--- team/russell/res_monkeys/apps/app_monkeys.c (original)
+++ team/russell/res_monkeys/apps/app_monkeys.c Tue Aug 28 15:33:47 2007
@@ -117,7 +117,7 @@
 
 	u = ast_module_user_add(chan);
 
-	if (ast_chan_thread_create(chan, monkey_thread))
+	if (ast_chan_thread_create(chan, NULL, monkey_thread, NULL, NULL))
 		res = -1;
 
 	ast_module_user_remove(u);

Modified: team/russell/res_monkeys/funcs/func_announce.c
URL: http://svn.digium.com/view/asterisk/team/russell/res_monkeys/funcs/func_announce.c?view=diff&rev=81289&r1=81288&r2=81289
==============================================================================
--- team/russell/res_monkeys/funcs/func_announce.c (original)
+++ team/russell/res_monkeys/funcs/func_announce.c Tue Aug 28 15:33:47 2007
@@ -38,48 +38,50 @@
 #include "asterisk/linkedlists.h"
 #include "asterisk/audiohook.h"
 
-static int unique_id;
-
 struct announce_data {
 	struct timeval begin;
 	int id;
 };
 
-static void announce_ds_destroy(void *arg)
+static void announce_data_destroy(void *data)
 {
-	struct announce_data *announce = arg;
+	struct announce_data *announce = data;
 
 	ast_free(announce);
 }
 
-static const struct ast_datastore_info announce_datastore = {
-	.type = "func_announce",
-	.destroy = announce_ds_destroy,
-};
+static void *announce_thread(void *data)
+{
+	struct ast_chan_thread_args *thread_args = data;
+	struct announce_data *announce = thread_args->data;
+
+	while (!thread_args->stop_thread) {
+		ast_mutex_lock(&thread_args->lock);
+		if (thread_args->stop_thread) {
+			ast_mutex_unlock(&thread_args->lock);
+			break;
+		}
+		ast_cond_wait(&thread_args->cond, &thread_args->lock);
+		ast_mutex_unlock(&thread_args->lock);
+	}
+
+	return announce;
+}
 
 static int start_announce_read(struct ast_channel *chan, const char *cmd, 
 	char *data, char *buf, size_t len)
 {
-	struct ast_datastore *datastore;
 	struct announce_data *announce;
 
 	if (!(announce = ast_calloc(1, sizeof(*announce))))
 		return -1;
 
-	announce->id = ast_atomic_fetchadd_int(&unique_id, +1);
 	announce->begin = ast_tvnow();
-	
+
+	ast_chan_thread_create(chan, &announce->id, announce_thread, 
+		announce, announce_data_destroy);
+
 	snprintf(buf, len, "%d", announce->id);
-
-	if (!(datastore = ast_channel_datastore_alloc(&announce_datastore, buf))) {
-		ast_free(announce);
-		buf[0] = '\0';
-		return -1;
-	}
-
-	ast_channel_lock(chan);
-	ast_channel_datastore_add(chan, datastore);
-	ast_channel_unlock(chan);
 
 	return 0;
 }
@@ -87,24 +89,24 @@
 static int stop_announce_read(struct ast_channel *chan, const char *cmd, 
 	char *data, char *buf, size_t len)
 {
-	struct ast_datastore *datastore;
 	struct announce_data *announce;
+	int id;
 
-	if (!(datastore = ast_channel_datastore_find(chan, &announce_datastore, data))) {
-		ast_log(LOG_WARNING, "Periodic Announcement with ID '%s' not found for channel '%s'\n",
-			data, chan->name);
+	if (sscanf(data, "%d", &id) != 1) {
+		ast_log(LOG_WARNING, "STOP_ANNOUNCE given invalid argument: '%s'\n", data);
 		return -1;
 	}
 
-	ast_channel_lock(chan);
-	ast_channel_datastore_remove(chan, datastore);
-	ast_channel_unlock(chan);
+	announce = ast_chan_thread_stop(chan, id);
 
-	announce = datastore->data;
+	if (!announce) {
+		ast_log(LOG_ERROR, "No Periodic announcement found for ID '%d'\n", id);
+		return -1;
+	}
 
 	snprintf(buf, len, "%d", ast_tvdiff_ms(ast_tvnow(), announce->begin));
 
-	ast_channel_datastore_free(datastore);
+	announce_data_destroy(announce);
 
 	return 0;
 }

Modified: team/russell/res_monkeys/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/russell/res_monkeys/include/asterisk/channel.h?view=diff&rev=81289&r1=81288&r2=81289
==============================================================================
--- team/russell/res_monkeys/include/asterisk/channel.h (original)
+++ team/russell/res_monkeys/include/asterisk/channel.h Tue Aug 28 15:33:47 2007
@@ -1466,13 +1466,19 @@
 
 struct ast_chan_thread_args {
 	struct ast_channel *chan;
+	int unique_id;
 	pthread_t thread_id;
+	void *data;
+	void (*data_destructor)(void *);
 	ast_mutex_t lock;
 	ast_cond_t cond;
 	unsigned int stop_thread:1;
 };
 
-int ast_chan_thread_create(struct ast_channel *chan, void *(*start_func)(void *));
+int ast_chan_thread_create(struct ast_channel *chan, int *id, void *(*start_func)(void *), 
+	void *data, void (*data_destructor)(void *));
+
+void *ast_chan_thread_stop(struct ast_channel *chan, int id);
 
 /*!
   \brief return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument

Modified: team/russell/res_monkeys/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/russell/res_monkeys/main/channel.c?view=diff&rev=81289&r1=81288&r2=81289
==============================================================================
--- team/russell/res_monkeys/main/channel.c (original)
+++ team/russell/res_monkeys/main/channel.c Tue Aug 28 15:33:47 2007
@@ -4732,3 +4732,96 @@
         snprintf(buf, sizeof(buf), "%d", num);
         return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
 }
+
+static void chan_thread_destroy(void *data);
+const struct ast_datastore_info chanthread_datastore_info = {
+	.type = "CHANTHREAD",
+	.destroy = chan_thread_destroy,
+};
+
+static void *destroy_chan_thread_args(struct ast_chan_thread_args *thread_args)
+{
+	void *ret = NULL;
+
+	if (thread_args->thread_id != AST_PTHREADT_NULL) {
+		ast_mutex_lock(&thread_args->lock);
+		thread_args->stop_thread = 1;
+		ast_cond_signal(&thread_args->cond);
+		ast_mutex_unlock(&thread_args->lock);
+		pthread_join(thread_args->thread_id, &ret);
+	}
+
+	ast_mutex_destroy(&thread_args->lock);
+	ast_cond_destroy(&thread_args->cond);
+
+	if (thread_args->data && thread_args->data_destructor) {
+		thread_args->data_destructor(thread_args->data);
+		thread_args->data = NULL;
+	}
+
+	ast_free(thread_args);
+
+	return ret;
+}
+
+void *ast_chan_thread_stop(struct ast_channel *chan, int id)
+{
+	struct ast_datastore *datastore;
+	struct ast_chan_thread_args *thread_args;
+	char id_str[32];
+
+	snprintf(id_str, sizeof(id_str), "%d", id);
+
+	ast_channel_lock(chan);
+	datastore = ast_channel_datastore_find(chan, &chanthread_datastore_info, id_str);
+	thread_args = datastore->data;
+	datastore->data = NULL;
+	ast_channel_unlock(chan);
+
+	return destroy_chan_thread_args(thread_args);
+}
+
+static void chan_thread_destroy(void *data)
+{
+	struct ast_chan_thread_args *thread_args = data;
+
+	destroy_chan_thread_args(thread_args);
+}
+
+static int chan_thread_id;
+
+int ast_chan_thread_create(struct ast_channel *chan, int *id, void *(*start_func)(void *), 
+	void *data, void (*data_destructor)(void *))
+{
+	struct ast_datastore *datastore;
+	struct ast_chan_thread_args *thread_args;
+	int res;
+	char buf[32];
+
+	if (!(thread_args = ast_calloc(1, sizeof(*thread_args))))
+		return -1;
+
+	thread_args->chan = chan;
+	thread_args->data = data;
+	thread_args->data_destructor = data_destructor;
+	ast_mutex_init(&thread_args->lock);
+	ast_cond_init(&thread_args->cond, NULL);
+	thread_args->thread_id = AST_PTHREADT_NULL;
+	thread_args->unique_id = ast_atomic_fetchadd_int(&chan_thread_id, +1);
+	if (id)
+		*id = thread_args->unique_id;
+
+	snprintf(buf, sizeof(buf), "%d", thread_args->unique_id);
+
+	if (!(datastore = ast_channel_datastore_alloc(&chanthread_datastore_info, buf))) {
+		ast_free(thread_args);
+		return -1;
+	}
+
+	ast_channel_lock(chan);
+	ast_channel_datastore_add(chan, datastore);
+	res = ast_pthread_create_background(&thread_args->thread_id, NULL, start_func, thread_args);
+	ast_channel_unlock(chan);
+
+	return res;
+}




More information about the asterisk-commits mailing list