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);


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to