[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