<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: LabVIEW Queued State Machine Architecture</title>
	<atom:link href="http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/feed/" rel="self" type="application/rss+xml" />
	<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/</link>
	<description>LabVIEW and visual programming blog</description>
	<lastBuildDate>Wed, 14 Dec 2011 00:11:04 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: LabBEAN1</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-7371</link>
		<dc:creator>LabBEAN1</dc:creator>
		<pubDate>Wed, 14 Dec 2011 00:11:04 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-7371</guid>
		<description>@Tekie:
I do not use the IDLE case in my own architecture, which is why this bit me a few years ago.  As you said, theoretically even with the IDLE state there is still the risk that states run in the wrong order without adding one of the workarounds you mentioned.  If you set up the architecture to allow all loops to enqueue to each other, you sort of need only one queue per loop (rather than the 2 queue model you mentioned).  That said, you can setup the Queue Manager to dynamically skip (etc.) the enqueue function if it detects a Stop (etc.) case in the queue.  Notes:  Good idea to avoid enqueueing on opposite end unless highly necessary AND do not enqueue states on opposite end that could take a while to run.

I like the idea of having the Event Structure outside the main while loop and of having multiple producer and producer/consumer loops (some of which live in task specific subVIs) the way the article describes.  One of the main advantages of putting the Event Structure outside the main loop above is that it keeps the main loop from free-wheeling just to handle the event structure, which makes debug much easier.  Including an IDLE state defeats this advantage.  The only reason for IDLE is to facilitate stopping all the loops via global Boolean.  Instead, I just enqueue SHUTDOWN to all the loops.  If you don&#039;t know how many loops you have before run time (i.e. you are spawning other loops dynamically), this is still easy to do by tracking the queues you&#039;ve created.

BTW, thanks for taking time to understand what I wrote.

@Peter
Consider using User Event architectures in combination with Queued architectures.  User Event architectures cause all loops to respond to all messages, which introduces unnecessary complexity (and free-wheeling) in most cases.  The important thing is to understand the tools and pull out the right one when necessary.  So, enqueue directly to the destination you want and, when necessary, broadcast to all processes via the User Event framework.  (Yes, you could just enqueue the same state to everybody as well.)

@String-State-Machine-Folks
I know you favor the use of type definitions elsewhere, so why not take advantage of them and make the switch to enum-based-state-machines (like I did several years ago).

-If you update the name of a state, all case structures and constants update too!
-Stop trying to remember what you called something.... or, worse, stop maintaining lists of state names so you can remember what you called something while declaring that maintaining an enum is too much work.  When you have multiple loops and 100+ states, I don&#039;t see how anyone tolerates strings.
-Can the LabVIEW run-time engine switch states (cases) as quickly on a string as it can on a U32?  (doubtful)
-Delete that &quot;whoops you mispelled the state name&quot; default state from all your loops.
-Passing data with the state you are enqueueing guarantees another state doesn&#039;t overwrite data you put on the main shift register (yes, some string folks add a &quot;state data&quot; variant or string as well, but most don&#039;t).
-Use a string where it&#039;s really valuable:  target to target communication (e.g. PC to cRIO).  I don&#039;t advocate using the same type defined enum for multiple targets since each gets it&#039;s own base code.  But, enjoy the enum when you&#039;re within the same target.  Then, convert the enum to string when sending over TCP/IP, Shared Variable, etc. and back to enum on the other side.

*LabBEAN1 = LabBEAN ... forgot password for LabBEAN and cannot receive emails where I created that account.</description>
		<content:encoded><![CDATA[<p>@Tekie:<br />
I do not use the IDLE case in my own architecture, which is why this bit me a few years ago.  As you said, theoretically even with the IDLE state there is still the risk that states run in the wrong order without adding one of the workarounds you mentioned.  If you set up the architecture to allow all loops to enqueue to each other, you sort of need only one queue per loop (rather than the 2 queue model you mentioned).  That said, you can setup the Queue Manager to dynamically skip (etc.) the enqueue function if it detects a Stop (etc.) case in the queue.  Notes:  Good idea to avoid enqueueing on opposite end unless highly necessary AND do not enqueue states on opposite end that could take a while to run.</p>
<p>I like the idea of having the Event Structure outside the main while loop and of having multiple producer and producer/consumer loops (some of which live in task specific subVIs) the way the article describes.  One of the main advantages of putting the Event Structure outside the main loop above is that it keeps the main loop from free-wheeling just to handle the event structure, which makes debug much easier.  Including an IDLE state defeats this advantage.  The only reason for IDLE is to facilitate stopping all the loops via global Boolean.  Instead, I just enqueue SHUTDOWN to all the loops.  If you don&#8217;t know how many loops you have before run time (i.e. you are spawning other loops dynamically), this is still easy to do by tracking the queues you&#8217;ve created.</p>
<p>BTW, thanks for taking time to understand what I wrote.</p>
<p>@Peter<br />
Consider using User Event architectures in combination with Queued architectures.  User Event architectures cause all loops to respond to all messages, which introduces unnecessary complexity (and free-wheeling) in most cases.  The important thing is to understand the tools and pull out the right one when necessary.  So, enqueue directly to the destination you want and, when necessary, broadcast to all processes via the User Event framework.  (Yes, you could just enqueue the same state to everybody as well.)</p>
<p>@String-State-Machine-Folks<br />
I know you favor the use of type definitions elsewhere, so why not take advantage of them and make the switch to enum-based-state-machines (like I did several years ago).</p>
<p>-If you update the name of a state, all case structures and constants update too!<br />
-Stop trying to remember what you called something&#8230;. or, worse, stop maintaining lists of state names so you can remember what you called something while declaring that maintaining an enum is too much work.  When you have multiple loops and 100+ states, I don&#8217;t see how anyone tolerates strings.<br />
-Can the LabVIEW run-time engine switch states (cases) as quickly on a string as it can on a U32?  (doubtful)<br />
-Delete that &#8220;whoops you mispelled the state name&#8221; default state from all your loops.<br />
-Passing data with the state you are enqueueing guarantees another state doesn&#8217;t overwrite data you put on the main shift register (yes, some string folks add a &#8220;state data&#8221; variant or string as well, but most don&#8217;t).<br />
-Use a string where it&#8217;s really valuable:  target to target communication (e.g. PC to cRIO).  I don&#8217;t advocate using the same type defined enum for multiple targets since each gets it&#8217;s own base code.  But, enjoy the enum when you&#8217;re within the same target.  Then, convert the enum to string when sending over TCP/IP, Shared Variable, etc. and back to enum on the other side.</p>
<p>*LabBEAN1 = LabBEAN &#8230; forgot password for LabBEAN and cannot receive emails where I created that account.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tekie</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-7315</link>
		<dc:creator>Tekie</dc:creator>
		<pubDate>Wed, 07 Dec 2011 00:03:26 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-7315</guid>
		<description>@LabBEAN:
I see the behaviour you explain, when you dont use an IDLE-state which add itself again. With the idle state it didnt happen, because the Consumer will be at least always working on the IDLE-state and adding it again in the same While-iteration. 

But I am not sure, whether it can happen, that the Idle-state-Consumer-iteration just ends and you add D right before the next iteration of the consumer starts. You want to add DCBA with the producer at the beginning of the queue, to get an ABCD-queue. Now the consumer works on the Idle state, but RIGHT after the idlestate iteration ends and BEFORE the new iteration starts, you add the D state. The chances for that to happen, should be ultra low, but perhaps it can happen.

To have no problem with that, you could add only A with the producer and let A add DCB within the queue manager. Or like you said, by using a dummy-state. Or you could use 2 queues:  One connecting the Producer with the queue-manager. And one connecting the queue-manager with the consumer. This could even solve problems like this: &quot;i added Stop state S at the beginning, while state A was working. Now A is finished and adds B at the beginning, which results in a BQ-queue.&quot;</description>
		<content:encoded><![CDATA[<p>@LabBEAN:<br />
I see the behaviour you explain, when you dont use an IDLE-state which add itself again. With the idle state it didnt happen, because the Consumer will be at least always working on the IDLE-state and adding it again in the same While-iteration. </p>
<p>But I am not sure, whether it can happen, that the Idle-state-Consumer-iteration just ends and you add D right before the next iteration of the consumer starts. You want to add DCBA with the producer at the beginning of the queue, to get an ABCD-queue. Now the consumer works on the Idle state, but RIGHT after the idlestate iteration ends and BEFORE the new iteration starts, you add the D state. The chances for that to happen, should be ultra low, but perhaps it can happen.</p>
<p>To have no problem with that, you could add only A with the producer and let A add DCB within the queue manager. Or like you said, by using a dummy-state. Or you could use 2 queues:  One connecting the Producer with the queue-manager. And one connecting the queue-manager with the consumer. This could even solve problems like this: &#8220;i added Stop state S at the beginning, while state A was working. Now A is finished and adds B at the beginning, which results in a BQ-queue.&#8221;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Aum-LabVIEW</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-7051</link>
		<dc:creator>Aum-LabVIEW</dc:creator>
		<pubDate>Mon, 04 Apr 2011 18:25:47 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-7051</guid>
		<description>Although ‘Queue State Machine’ is the most popular architecture following industry standards, no other article on QSM using LabVIEW till date is even closely as exhaustive, to the point and explanative.
Takes care of the LabVIEW execution system threads as well.
Great blog &amp; great article.</description>
		<content:encoded><![CDATA[<p>Although ‘Queue State Machine’ is the most popular architecture following industry standards, no other article on QSM using LabVIEW till date is even closely as exhaustive, to the point and explanative.<br />
Takes care of the LabVIEW execution system threads as well.<br />
Great blog &amp; great article.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: durnek60</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-7040</link>
		<dc:creator>durnek60</dc:creator>
		<pubDate>Fri, 19 Nov 2010 06:10:41 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-7040</guid>
		<description>Very nice job! Thanks for sharing!</description>
		<content:encoded><![CDATA[<p>Very nice job! Thanks for sharing!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: YuvalYohai</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-7026</link>
		<dc:creator>YuvalYohai</dc:creator>
		<pubDate>Mon, 21 Jun 2010 11:31:32 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-7026</guid>
		<description>Hi Anthony,

Beautiful article.
I&#039;ve been using my own LV state machine architecture for a long time. Your architecture is the last leap I needed in order to make them more robust.
Thanks very much.

good luck,
Yuval Yohai</description>
		<content:encoded><![CDATA[<p>Hi Anthony,</p>
<p>Beautiful article.<br />
I&#8217;ve been using my own LV state machine architecture for a long time. Your architecture is the last leap I needed in order to make them more robust.<br />
Thanks very much.</p>
<p>good luck,<br />
Yuval Yohai</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: LabBEAN</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-6992</link>
		<dc:creator>LabBEAN</dc:creator>
		<pubDate>Tue, 12 Jan 2010 23:20:39 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-6992</guid>
		<description>Hi Anthony,

Let&#039;s say one of the producers (see the red &quot;4.1&quot; in Figure 2 above) enqueues states on the opposite end to the consumer (see the red &quot;3&quot; in Figure 2 above).  When the first state is enqueued, then the consumer will immediately dequeue it because the consumer is waiting to dequeue an element.  If you enqueue the elements in reverse order (which I agree *of course* that reversing the order first is necessary since they are each being enqueued on opposite end), then the elements will run in the order &quot;last&quot;, &quot;first&quot;, &quot;second&quot;, &quot;third&quot;, &quot;...&quot;, &quot;next to last&quot;.  You need to enqueue a dummy element on opposite end first.

Note:  This is not the case when enqueueing within the same consumer (because of data flow) or for any future elements after the first element enqueued on opposite end when enqueueing from producer to consumer (as long as the Q MGR [see red &quot;1.5&quot; in Figure 2] is non-reentrant).

Please reread my previous post.

Take care,
Jason</description>
		<content:encoded><![CDATA[<p>Hi Anthony,</p>
<p>Let&#8217;s say one of the producers (see the red &#8220;4.1&#8243; in Figure 2 above) enqueues states on the opposite end to the consumer (see the red &#8220;3&#8243; in Figure 2 above).  When the first state is enqueued, then the consumer will immediately dequeue it because the consumer is waiting to dequeue an element.  If you enqueue the elements in reverse order (which I agree *of course* that reversing the order first is necessary since they are each being enqueued on opposite end), then the elements will run in the order &#8220;last&#8221;, &#8220;first&#8221;, &#8220;second&#8221;, &#8220;third&#8221;, &#8220;&#8230;&#8221;, &#8220;next to last&#8221;.  You need to enqueue a dummy element on opposite end first.</p>
<p>Note:  This is not the case when enqueueing within the same consumer (because of data flow) or for any future elements after the first element enqueued on opposite end when enqueueing from producer to consumer (as long as the Q MGR [see red "1.5" in Figure 2] is non-reentrant).</p>
<p>Please reread my previous post.</p>
<p>Take care,<br />
Jason</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Anthony Lukindo</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-6991</link>
		<dc:creator>Anthony Lukindo</dc:creator>
		<pubDate>Mon, 11 Jan 2010 05:26:23 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-6991</guid>
		<description>Hi LabBEAN:

The need to reverse the order of multiple events added to the front of the queue is correct. This is implemented in Figure 9 of the article. Notice the &#039;Reverse 1D array node.&#039; Thus events are always reversed by the queue manager subVI when added to the front of the queue.</description>
		<content:encoded><![CDATA[<p>Hi LabBEAN:</p>
<p>The need to reverse the order of multiple events added to the front of the queue is correct. This is implemented in Figure 9 of the article. Notice the &#8216;Reverse 1D array node.&#8217; Thus events are always reversed by the queue manager subVI when added to the front of the queue.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: LabBEAN</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-6989</link>
		<dc:creator>LabBEAN</dc:creator>
		<pubDate>Wed, 06 Jan 2010 20:42:49 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-6989</guid>
		<description>As I mentioned here:
http://decibel.ni.com/content/message/11700#11700

Regarding the implementation of enqueueing on opposite end (front of the queue):  When you enqueue multiple items on the opposite end to another loop which is waiting to dequeue elements [where execution order is critical (e.g. State 1, State 2, State 3, State 4)], the waiting loop will dequeue and run State 4 first.  Here&#039;s why:  Before enqueueing the 4 states on the opposite end, you must first reverse their order.  When another loop is waiting to dequeue, it grabs the first item you enqueue (e.g. State 4).  It&#039;s not a concern that it grab subsequent items, regardless of execution speed, since all loops share the same non-reentrant Queue Manager, and the only instance of the Queue Manager is busy enqueueing the next three states (in this example).  Therefore, you could end up with an execution order of State 4, State 1, State 2, State 3.  So, I would suggest enqueueing a dummy state before enqueueing on opposite end your states in reverse order.

Else, odd behaviour can occur (e.g. Stop state occurs before Power Supply Off state *ouch*).</description>
		<content:encoded><![CDATA[<p>As I mentioned here:<br />
<a href="http://decibel.ni.com/content/message/11700#11700" rel="nofollow">http://decibel.ni.com/content/message/11700#11700</a></p>
<p>Regarding the implementation of enqueueing on opposite end (front of the queue):  When you enqueue multiple items on the opposite end to another loop which is waiting to dequeue elements [where execution order is critical (e.g. State 1, State 2, State 3, State 4)], the waiting loop will dequeue and run State 4 first.  Here&#8217;s why:  Before enqueueing the 4 states on the opposite end, you must first reverse their order.  When another loop is waiting to dequeue, it grabs the first item you enqueue (e.g. State 4).  It&#8217;s not a concern that it grab subsequent items, regardless of execution speed, since all loops share the same non-reentrant Queue Manager, and the only instance of the Queue Manager is busy enqueueing the next three states (in this example).  Therefore, you could end up with an execution order of State 4, State 1, State 2, State 3.  So, I would suggest enqueueing a dummy state before enqueueing on opposite end your states in reverse order.</p>
<p>Else, odd behaviour can occur (e.g. Stop state occurs before Power Supply Off state *ouch*).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: harbenger</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-6988</link>
		<dc:creator>harbenger</dc:creator>
		<pubDate>Sun, 27 Dec 2009 04:59:41 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-6988</guid>
		<description>I agree with everything you say. However, my concern was centered around the management of the queue. In order to completely flush the queue, you either need to have states with no next-state enqueues (which will have a net loss in the queue size) or manually flush the queue. The idle state has a zero net loss of the queue size.

Consider my example again. You have two idle-like loops which place default next-state commands into the queue. Likewise, you have two events which allow you to switch between loops. Each state by itself will not change the size of your queue. However, your queue will continue to fill up with unserviced next-state requests as you switch between states. This is true because the event loop is the primary producer of queue elements and the consumer loop has a net zero loss.

You can confirm this by adding queue status VI&#039;s either in-loop or as a separate loop.

I was able to fix this by adding more functionality to your Q Manager.vi. I&#039;m not completely sold on it being complete, but the idea is as follows: Define a &#039;default&#039; next state transition as a boolean input. Only add the default next-state element to the queue if your queue is empty. Otherwise, don&#039;t add it. This will fix the always increasing queue size problem.</description>
		<content:encoded><![CDATA[<p>I agree with everything you say. However, my concern was centered around the management of the queue. In order to completely flush the queue, you either need to have states with no next-state enqueues (which will have a net loss in the queue size) or manually flush the queue. The idle state has a zero net loss of the queue size.</p>
<p>Consider my example again. You have two idle-like loops which place default next-state commands into the queue. Likewise, you have two events which allow you to switch between loops. Each state by itself will not change the size of your queue. However, your queue will continue to fill up with unserviced next-state requests as you switch between states. This is true because the event loop is the primary producer of queue elements and the consumer loop has a net zero loss.</p>
<p>You can confirm this by adding queue status VI&#8217;s either in-loop or as a separate loop.</p>
<p>I was able to fix this by adding more functionality to your Q Manager.vi. I&#8217;m not completely sold on it being complete, but the idea is as follows: Define a &#8216;default&#8217; next state transition as a boolean input. Only add the default next-state element to the queue if your queue is empty. Otherwise, don&#8217;t add it. This will fix the always increasing queue size problem.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Anthony Lukindo</title>
		<link>http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/comment-page-1/#comment-6987</link>
		<dc:creator>Anthony Lukindo</dc:creator>
		<pubDate>Thu, 24 Dec 2009 04:16:14 +0000</pubDate>
		<guid isPermaLink="false">http://expressionflow.com/2007/10/01/labview-queued-state-machine-architecture/#comment-6987</guid>
		<description>Harbenger:

Just wanted to comment on the idle state case. Note that the idle event is added at the end of the array build node. This means that any events added to the array build node, prior to the idle event, will run first. 

Also, the idle event should only be added in the idle case to indicate an eventual return to that case for polling or looping purposes. Alternatively you can omit adding the idle event to keep the program &#039;silent&#039; so that it only wakes-up and acts when some new event is added to queue.

Finally, take note that as you add events to the queue in other cases you have the option of adding them to the &#039;front of the queue&#039; so that they get executed immediately. This means that the event will be jumping the queue and will be immediately de-queued for execution.


I hope this further clarifies things</description>
		<content:encoded><![CDATA[<p>Harbenger:</p>
<p>Just wanted to comment on the idle state case. Note that the idle event is added at the end of the array build node. This means that any events added to the array build node, prior to the idle event, will run first. </p>
<p>Also, the idle event should only be added in the idle case to indicate an eventual return to that case for polling or looping purposes. Alternatively you can omit adding the idle event to keep the program &#8216;silent&#8217; so that it only wakes-up and acts when some new event is added to queue.</p>
<p>Finally, take note that as you add events to the queue in other cases you have the option of adding them to the &#8216;front of the queue&#8217; so that they get executed immediately. This means that the event will be jumping the queue and will be immediately de-queued for execution.</p>
<p>I hope this further clarifies things</p>
]]></content:encoded>
	</item>
</channel>
</rss>

