[asterisk-commits] russell: branch russell/chan_refcount r82301 - /team/russell/chan_refcount/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Sep 12 17:48:03 CDT 2007


Author: russell
Date: Wed Sep 12 17:48:03 2007
New Revision: 82301

URL: http://svn.digium.com/view/asterisk?view=rev&rev=82301
Log:
add the destructor

Modified:
    team/russell/chan_refcount/main/channel.c

Modified: team/russell/chan_refcount/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/channel.c?view=diff&rev=82301&r1=82300&r2=82301
==============================================================================
--- team/russell/chan_refcount/main/channel.c (original)
+++ team/russell/chan_refcount/main/channel.c Wed Sep 12 17:48:03 2007
@@ -610,6 +610,121 @@
 	.description = "Null channel (should not see this)",
 };
 
+static void free_cid(struct ast_callerid *cid)
+{
+	if (cid->cid_dnid)
+		ast_free(cid->cid_dnid);
+	if (cid->cid_num)
+		ast_free(cid->cid_num);	
+	if (cid->cid_name)
+		ast_free(cid->cid_name);	
+	if (cid->cid_ani)
+		ast_free(cid->cid_ani);
+	if (cid->cid_rdnis)
+		ast_free(cid->cid_rdnis);
+	cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
+}
+
+struct ast_channel *ast_channel_free(struct ast_channel *chan)
+{	
+	/* Safe, even if already unlinked. */
+	ao2_unlink(channels, chan);
+	return ast_channel_unref(chan);
+}
+
+static int ast_channel_destructor(void *data)
+{
+	struct ast_channel *chan = data;
+	int fd;
+#ifdef HAVE_EPOLL
+	int i;
+#endif
+	struct ast_var_t *vardata;
+	struct ast_frame *f;
+	struct varshead *headp;
+	struct ast_datastore *datastore = NULL;
+	char name[AST_CHANNEL_NAME];
+	
+	headp=&chan->varshead;
+	
+	AST_RWLIST_WRLOCK(&channels);
+	if (!AST_RWLIST_REMOVE(&channels, chan, chan_list)) {
+		AST_RWLIST_UNLOCK(&channels);
+		ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
+	}
+	/* Lock and unlock the channel just to be sure nobody
+	   has it locked still */
+	ast_channel_lock(chan);
+	ast_channel_unlock(chan);
+	if (chan->tech_pvt) {
+		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
+		ast_free(chan->tech_pvt);
+	}
+
+	if (chan->sched)
+		sched_context_destroy(chan->sched);
+
+	ast_copy_string(name, chan->name, sizeof(name));
+
+	/* Stop monitoring */
+	if (chan->monitor)
+		chan->monitor->stop( chan, 0 );
+
+	/* If there is native format music-on-hold state, free it */
+	if (chan->music_state)
+		ast_moh_cleanup(chan);
+
+	/* Free translators */
+	if (chan->readtrans)
+		ast_translator_free_path(chan->readtrans);
+	if (chan->writetrans)
+		ast_translator_free_path(chan->writetrans);
+	if (chan->pbx)
+		ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
+	free_cid(&chan->cid);
+	ast_mutex_destroy(&chan->lock);
+	/* Close pipes if appropriate */
+	if ((fd = chan->alertpipe[0]) > -1)
+		close(fd);
+	if ((fd = chan->alertpipe[1]) > -1)
+		close(fd);
+	if ((fd = chan->timingfd) > -1)
+		close(fd);
+#ifdef HAVE_EPOLL
+	for (i = 0; i < AST_MAX_FDS; i++) {
+		if (chan->epfd_data[i])
+			free(chan->epfd_data[i]);
+	}
+	close(chan->epfd);
+#endif
+	while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list)))
+		ast_frfree(f);
+	
+	/* Get rid of each of the data stores on the channel */
+	while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
+		/* Free the data store */
+		ast_channel_datastore_free(datastore);
+	AST_LIST_HEAD_INIT_NOLOCK(&chan->datastores);
+
+	/* loop over the variables list, freeing all data and deleting list items */
+	/* no need to lock the list, as the channel is already locked */
+	
+	while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
+		ast_var_delete(vardata);
+
+	ast_app_group_discard(chan);
+
+	/* Destroy the jitterbuffer */
+	ast_jb_destroy(chan);
+
+	ast_string_field_free_pools(chan);
+	ast_free(chan);
+	AST_RWLIST_UNLOCK(&channels);
+
+	ast_device_state_changed_literal(name);
+}
+
+
 /*! \brief Create a new channel structure */
 struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
 {
@@ -625,18 +740,16 @@
 		return NULL;
 	}
 
-	if (!(tmp = ast_calloc(1, sizeof(*tmp))))
+	if (!(tmp = ao2_alloc(sizeof(*tmp), ast_channel_destructor)))
 		return NULL;
 
 	if (!(tmp->sched = sched_context_create())) {
-		ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
-		ast_free(tmp);
+		ast_channel_unref(tmp);
 		return NULL;
 	}
 	
 	if ((ast_string_field_init(tmp, 128))) {
-		sched_context_destroy(tmp->sched);
-		ast_free(tmp);
+		ast_channel_unref(tmp);
 		return NULL;
 	}
 
@@ -667,8 +780,7 @@
 	if (needqueue) {
 		if (pipe(tmp->alertpipe)) {
 			ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe!\n");
-			ast_string_field_free_pools(tmp);
-			ast_free(tmp);
+			ast_channel_unref(tmp);
 			return NULL;
 		} else {
 			flags = fcntl(tmp->alertpipe[0], F_GETFL);
@@ -775,9 +887,7 @@
 
 	tmp->tech = &null_tech;
 
-	AST_RWLIST_WRLOCK(&channels);
-	AST_RWLIST_INSERT_HEAD(&channels, tmp, chan_list);
-	AST_RWLIST_UNLOCK(&channels);
+	ao2_link(channels, ast_channel_ref(tmp));
 
 	return tmp;
 }
@@ -1058,113 +1168,6 @@
 int ast_safe_sleep(struct ast_channel *chan, int ms)
 {
 	return ast_safe_sleep_conditional(chan, ms, NULL, NULL);
-}
-
-static void free_cid(struct ast_callerid *cid)
-{
-	if (cid->cid_dnid)
-		ast_free(cid->cid_dnid);
-	if (cid->cid_num)
-		ast_free(cid->cid_num);	
-	if (cid->cid_name)
-		ast_free(cid->cid_name);	
-	if (cid->cid_ani)
-		ast_free(cid->cid_ani);
-	if (cid->cid_rdnis)
-		ast_free(cid->cid_rdnis);
-	cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
-}
-
-/*! \brief Free a channel structure */
-void ast_channel_free(struct ast_channel *chan)
-{
-	int fd;
-#ifdef HAVE_EPOLL
-	int i;
-#endif
-	struct ast_var_t *vardata;
-	struct ast_frame *f;
-	struct varshead *headp;
-	struct ast_datastore *datastore = NULL;
-	char name[AST_CHANNEL_NAME];
-	
-	headp=&chan->varshead;
-	
-	AST_RWLIST_WRLOCK(&channels);
-	if (!AST_RWLIST_REMOVE(&channels, chan, chan_list)) {
-		AST_RWLIST_UNLOCK(&channels);
-		ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
-	}
-	/* Lock and unlock the channel just to be sure nobody
-	   has it locked still */
-	ast_channel_lock(chan);
-	ast_channel_unlock(chan);
-	if (chan->tech_pvt) {
-		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
-		ast_free(chan->tech_pvt);
-	}
-
-	if (chan->sched)
-		sched_context_destroy(chan->sched);
-
-	ast_copy_string(name, chan->name, sizeof(name));
-
-	/* Stop monitoring */
-	if (chan->monitor)
-		chan->monitor->stop( chan, 0 );
-
-	/* If there is native format music-on-hold state, free it */
-	if (chan->music_state)
-		ast_moh_cleanup(chan);
-
-	/* Free translators */
-	if (chan->readtrans)
-		ast_translator_free_path(chan->readtrans);
-	if (chan->writetrans)
-		ast_translator_free_path(chan->writetrans);
-	if (chan->pbx)
-		ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
-	free_cid(&chan->cid);
-	ast_mutex_destroy(&chan->lock);
-	/* Close pipes if appropriate */
-	if ((fd = chan->alertpipe[0]) > -1)
-		close(fd);
-	if ((fd = chan->alertpipe[1]) > -1)
-		close(fd);
-	if ((fd = chan->timingfd) > -1)
-		close(fd);
-#ifdef HAVE_EPOLL
-	for (i = 0; i < AST_MAX_FDS; i++) {
-		if (chan->epfd_data[i])
-			free(chan->epfd_data[i]);
-	}
-	close(chan->epfd);
-#endif
-	while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list)))
-		ast_frfree(f);
-	
-	/* Get rid of each of the data stores on the channel */
-	while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
-		/* Free the data store */
-		ast_channel_datastore_free(datastore);
-	AST_LIST_HEAD_INIT_NOLOCK(&chan->datastores);
-
-	/* loop over the variables list, freeing all data and deleting list items */
-	/* no need to lock the list, as the channel is already locked */
-	
-	while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
-		ast_var_delete(vardata);
-
-	ast_app_group_discard(chan);
-
-	/* Destroy the jitterbuffer */
-	ast_jb_destroy(chan);
-
-	ast_string_field_free_pools(chan);
-	ast_free(chan);
-	AST_RWLIST_UNLOCK(&channels);
-
-	ast_device_state_changed_literal(name);
 }
 
 struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, const char *uid)




More information about the asterisk-commits mailing list