<html>
 <body>
  <div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
   <table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
    <tr>
     <td>
      This is an automatically generated e-mail. To reply, visit:
      <a href="https://reviewboard.asterisk.org/r/2072/">https://reviewboard.asterisk.org/r/2072/</a>
     </td>
    </tr>
   </table>
   <br />





<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
 <p style="margin-top: 0;">On August 23rd, 2012, 5:43 p.m., <b>jrose</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Overall I think this is a very sensible way to solve this problem. One thing that might be worth considering though is that you are handling state transition behavior as part of the events that take place when you are going to change state, and it might eventually be the case that there are multiple ways to perform the same transition. I think transition behavior as well as the state change itself should be put into a separate function from where the need for a state change is determined. That&#39;s something that could be broken out at any time though.</pre>
 </blockquote>




 <p>On August 23rd, 2012, 7:58 p.m., <b>Terry Wilson</b> wrote:</p>
 <blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
  <pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">I may be misunderstanding what you are saying, and if I am please correct me.

Transition behavior is determined by A) the conf_change_state function (call the state exit, change the state, call the next state entry) and B) what actually happens in those state exit/entry functions. The behavior in the events handlers isn&#39;t transition behavior, it is event-related behavior that may or may not result in a state change. You *can&#39;t* separate out the behavior in the event handlers because you need to actually do a certain action, for example,  *every single time* that an unmarked leaves a conference in the MULTI state regardless of whether it leads to a state change.</pre>
 </blockquote>








</blockquote>

<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">What I&#39;m actually saying is that a part of the behavior of a state machine from how I learned it is that each change from a state of one type to another can have specific behavior that really only applies to that particular transition.

There aren&#39;t really any examples of it in the code now, but if there were multiple conditions for going from state A to state B that all shared some kind of common action that they take, you could simple pull that code out of the conditions that you use to evaluate whether the state change is necessary along with the call to change the state itself and put it into a specific state A to state B transition function that you call from within your handling function.



For the sake of example, I&#39;m just going to pretend that you could want to be adding specific debug statements saying that one state is being exited to enter another... which for some completely arbitrary reason doesn&#39;t belong in the generic state change function (because it&#39;s just an example). Say we are in CONF_STATE_MARKED and an active user leaves and we determine that we need to do the state change to SINGLE_MARKED because it was the last one.

Rather than calling the generic state change function in this condition to go into SINGLE_MARKED, you have another function in your state which isn&#39;t referenced as a callback, called something like:

static void transition_to_single_marked(struct conference_bridge_user *cbu) {
    ast_debug(3, &quot;Some message about how we are changing from MULTI_MARKED to SINGLE_MARKED\n&quot;);
    /* Insert other future behavior here */

    conf_change_state(cbu, CONF_STATE_SINGLE_MARKED);
}

the leave_active function in your MULTI_MARKED would then be:
static void leave_active(struct conference_bridge_user *cbu)
{
    conf_remove_user_active(cbu-&gt;conference_bridge, cbu);
    if (cbu-&gt;conference_bridge-&gt;activeusers == 1) {
        transition_to_single_marked();
    }
}

It&#39;s totally unnecessary and it&#39;s really easy to change if the need arises, but in some possible future scenario where mutants with a penchant for open source software are running the Asterisk project and they decide for some reason to add some new kinds of users that can cause the same transitions under different conditions, it could help to avoid duplicate code.</pre>
<br />








<p>- jrose</p>


<br />
<p>On August 23rd, 2012, 11:01 a.m., Terry Wilson wrote:</p>






<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('https://reviewboard.asterisk.org/media/rb/images/review_request_box_top_bg.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
 <tr>
  <td>

<div>Review request for Asterisk Developers and Neil Tallim.</div>
<div>By Terry Wilson.</div>


<p style="color: grey;"><i>Updated Aug. 23, 2012, 11:01 a.m.</i></p>




<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Thank&#39;s to flan&#39;s tireless testing, issue reporting, and patches it became clear that app_confbridge had some complex logic and was missing some corner cases. In particular, it didn&#39;t handle mixing unmarked and waitmarked users very well and was inconsistent in how MOH and muting was applied.  flan&#39;s patches seem to fix the issue, but they highlight how hard the code could be to maintain. In an attempt to make things easier to maintain and to more fully enumerate the various cases that exist, I have attempted to break up the logic into a state machine-like setup.

This should fix all of the issues in the linked bugs, as well as a couple of other issues. I still need to add some documentation, but I thought I&#39;d give people a chance to look at it test it out, and comment.

One thing to note is that this solution involves treating waitmarked users without a marked user as essentially outside of the conference. For now, I have the announce_user_count stuff taking into account both the counts for waiting and active users which can lead to things like having a single waiting user followed by an unmarked user and the announcement that &quot;there is one other user in the conference&quot; (because we count the waiting user there) followed by &quot;you are the only user in the conference&quot; (because that prompt plays when you are the only active user) being played to the unmarked user. This is easy to fix, we just need to decide which way to go. Count users who are essentially outside the conference (they can&#39;t speak or hear) or not?</pre>
  </td>
 </tr>
</table>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
 <tr>
  <td>
   <pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Lots of calls. Need to do more formalized testing.</pre>
  </td>
 </tr>
</table>



<div style="margin-top: 1.5em;">
 <b style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Bugs: </b>


 <a href="https://issues.asterisk.org/jira/browse/ASTERISK-19562">ASTERISK-19562</a>, 

 <a href="https://issues.asterisk.org/jira/browse/ASTERISK-19726">ASTERISK-19726</a>, 

 <a href="https://issues.asterisk.org/jira/browse/ASTERISK-20181">ASTERISK-20181</a>


</div>


<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">

 <li>/branches/10/apps/app_confbridge.c <span style="color: grey">(371641)</span></li>

 <li>/branches/10/apps/confbridge/conf_state.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_empty.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_inactive.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_marked.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_multi.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_single.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/conf_state_single_marked.c <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/include/conf_state.h <span style="color: grey">(PRE-CREATION)</span></li>

 <li>/branches/10/apps/confbridge/include/confbridge.h <span style="color: grey">(371641)</span></li>

</ul>

<p><a href="https://reviewboard.asterisk.org/r/2072/diff/" style="margin-left: 3em;">View Diff</a></p>




  </td>
 </tr>
</table>








  </div>
 </body>
</html>