[asterisk-commits] dlee: branch dlee/ASTERISK-22243 r396355 - in /team/dlee/ASTERISK-22243: cont...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Aug 7 10:11:09 CDT 2013
Author: dlee
Date: Wed Aug 7 10:11:07 2013
New Revision: 396355
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396355
Log:
Comments
Modified:
team/dlee/ASTERISK-22243/contrib/asterisk-ng-doxygen
team/dlee/ASTERISK-22243/main/stasis.c
Modified: team/dlee/ASTERISK-22243/contrib/asterisk-ng-doxygen
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22243/contrib/asterisk-ng-doxygen?view=diff&rev=396355&r1=396354&r2=396355
==============================================================================
--- team/dlee/ASTERISK-22243/contrib/asterisk-ng-doxygen (original)
+++ team/dlee/ASTERISK-22243/contrib/asterisk-ng-doxygen Wed Aug 7 10:11:07 2013
@@ -34,7 +34,7 @@
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = SVN-dlee-ASTERISK-22243-URL:-r396345M-/trunk
+PROJECT_NUMBER = SVN-dlee-ASTERISK-22243-URL:-r396348M-/trunk
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
Modified: team/dlee/ASTERISK-22243/main/stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22243/main/stasis.c?view=diff&rev=396355&r1=396354&r2=396355
==============================================================================
--- team/dlee/ASTERISK-22243/main/stasis.c (original)
+++ team/dlee/ASTERISK-22243/main/stasis.c Wed Aug 7 10:11:07 2013
@@ -45,9 +45,8 @@
* \par Reference counting
*
* Stasis introduces a number of objects, which are tightly related to one
- * another. Since C relies on manual memory management, and we rely on
- * ref-counting, understanding these relationships is important to understanding
- * this code.
+ * another. Because we rely on ref-counting for memory management, understanding
+ * these relationships is important to understanding this code.
*
* \code{.txt}
*
@@ -72,16 +71,20 @@
* necessary. Topics need the subscription in order to dispatch messages;
* subscriptions need the topics to unsubscribe and check subscription status.
*
- * To balance the cycle, the reference from the subscription to the topic is
- * considered the 'master', and the topic does _not_ bump the refcount on the
- * subscription. A topic will not be destroyed until it has no subscribers.
- *
- * The dispatch object is a transient object, which is mailed to a
- * subscription's taskprocessor to send a message to the subscriber. They tend
- * to have short and fast life cycles, allocated on one thread, destroyed on
- * another.
- *
- * During shutdown, or the deletion of objects, there are a flurry of
+ * The cycle is broken by stasis_unsubscribe(). The unsubscribe will remove the
+ * topic's reference to a subscription. When the subcription is destroyed, it
+ * will remove its reference to the topic.
+ *
+ * This means that until a subscription has be explicitly unsubscribed, it will
+ * not be destroyed. Neither will a topic be destroyed while it has subscribers.
+ * The destructors of both have assertions regarding this to catch ref-counting
+ * problems where a subscription or topic has had an extra ao2_cleanup().
+ *
+ * The \ref dispatch object is a transient object, which is posted to a
+ * subscription's taskprocessor to send a message to the subscriber. They have
+ * short life cycles, allocated on one thread, destroyed on another.
+ *
+ * During shutdown, or the deletion of a domain object, there are a flurry of
* ao2_cleanup()s on subscriptions and topics, as the final in-flight messages
* are processed. Any one of these cleanups could be the one to actually destroy
* a given object, so care must be taken to ensure that an object isn't
@@ -95,15 +98,19 @@
* are actually fed by shorter-lived topics whose lifetime is associated
* with some domain object (like ast_channel_topic() for a given
* ast_channel).
+ *
* \li stasis_subscription - Subscriptions have a similar mix of lifetimes as
* topics, for similar reasons.
+ *
* \li dispatch - Very short lived; just long enough to post a message to a
* subscriber.
+ *
* \li stasis_message - Short to intermediate lifetimes, but that is mostly
* irrelevant. Messages are strictly data and have no behavior associated
- * with them, so it doesn't really matter if/when/how they are destroyed.
- * By design, some component could hold a ref to a message forever without
- * any ill consequences (aside from consuming more memory).
+ * with them, so it doesn't really matter if/when they are destroyed. By
+ * design, a component could hold a ref to a message forever without any
+ * ill consequences (aside from consuming more memory).
+ *
* \li stasis_message_type - Long life cycles, typically only destroyed on
* module unloading or _clean_ process exit.
*
@@ -112,6 +119,13 @@
* Subscribers are sensitive to shutdown sequencing, specifically in how the
* reference message types. This is fully detailed on the wiki at
* https://wiki.asterisk.org/wiki/x/K4BqAQ.
+ *
+ * In short, the lifetime of the \a data (and \a callback, if in a module) must
+ * be held until the stasis_subscription_final_message() has been received.
+ * Depending on the structure of the subscriber code, this can be handled by
+ * using stasis_subscription_final_message() to free resources on the final
+ * message, or using stasis_subscription_join()/stasis_unsubscribe_and_join() to
+ * block until the unsubscribe has completed.
*/
/*! Initial size of the subscribers list. */
@@ -128,7 +142,7 @@
/*! \internal */
struct stasis_topic {
char *name;
- /*! Variable length array of the subscribers. */
+ /*! Variable length array of the subscribers */
struct stasis_subscription **subscribers;
/*! Allocated length of the subscribers array */
size_t num_subscribers_max;
@@ -143,9 +157,8 @@
{
struct stasis_topic *topic = obj;
- /* Subscribers hold a refernce to topics, so they should all be
- * unsubscribed before we get here.
- */
+ /* Subscribers hold a reference to topics, so they should all be
+ * unsubscribed before we get here. */
ast_assert(topic->num_subscribers_current == 0);
ast_free(topic->name);
topic->name = NULL;
@@ -196,7 +209,7 @@
/*! Data pointer to be handed to the callback. */
void *data;
- /*! Lock for joining with subscription. */
+ /*! Lock for completion flags \c final_message_{rxed,processed}. */
ast_mutex_t join_lock;
/*! Condition for joining with subscription. */
ast_cond_t join_cond;
@@ -329,11 +342,6 @@
return NULL;
}
-/*!
- * \brief Block until the final message has been received on a subscription.
- *
- * \param subscription Subscription to wait on.
- */
void stasis_subscription_join(struct stasis_subscription *subscription)
{
if (subscription) {
@@ -436,7 +444,12 @@
topic->num_subscribers_max *= 2;
}
- /* Don't ref sub here or we'll cause a reference cycle. */
+ /* The reference from the topic to the subscription is shared with
+ * the owner of the subscription, which will explicitly unsubscribe
+ * to release it.
+ *
+ * If we bumped the refcount here, the owner would have to unsubscribe
+ * and cleanup, which is a bit awkward. */
topic->subscribers[topic->num_subscribers_current++] = sub;
return 0;
}
@@ -505,9 +518,8 @@
void stasis_forward_message(struct stasis_topic *t, struct stasis_topic *publisher_topic, struct stasis_message *message)
{
size_t i;
- /* The dispatch may dispose of the final reference to the topic. Hold
- * it open until after the unlock.
- */
+ /* The topic may be unref'ed by the subscription invocation.
+ * Make sure we hold onto a reference while dispatching. */
RAII_VAR(struct stasis_topic *, topic, ao2_ref1(t), ao2_cleanup);
SCOPED_AO2LOCK(lock, topic);
@@ -718,7 +730,7 @@
ast_log(LOG_ERROR, "Use of %s() before init/after destruction\n", name);
}
-/*! \brief Cleanup function */
+/*! \brief Shutdown function */
static void stasis_exit(void)
{
ast_threadpool_shutdown(pool);
More information about the asterisk-commits
mailing list