BreakPoint

cancel
Showing results for 
Search instead for 
Did you mean: 

Queued State Machine pro and contra, snakes eating themself, suggestions for better programming designs, etc...

Hello,

 

We started a little bit more general parallel discussion in a recent post, from this point:

http://forums.ni.com/t5/LabVIEW/producer-consumer-code-with-several-variables-types/m-p/3558204/high...

I think it is better to de-couple this discussion from the actual problem of the OP, so I just created here in BreakPoint this, to discuss further this interesting topic (of course only if you wish, but I feel I started to learn again some new things from some of you, and to see my programming style from a different aspect).

 

So to pick up the line from the last question, from the last post:

 

Bob you just gave me the last push, I just have to start playing with these Channels on the incoming weekend 🙂 However one question regarind to this part: "Notice the Messenger Channel coming out of the State Machine (specifically coming out of the Error Handler), which allows the State Machine to send itself State Information.  Such "looping" behavior is not that evident in this part of the code, but is important in the Producer."

 

Is there no such danger as in the case of QSM explained before (self enqueue-ing consumer), I feel the logic is the same (similar?) here?

 

Edit: and thanks Ben, I also learned a new word "Ouroboros" from your post! 🙂

https://en.wikipedia.org/wiki/Ouroboros

 

470px-Ouroboros_1.jpg

Message 1 of 17
(10,478 Views)

Blokk wrote:  Is there no such danger as in the case of QSM explained before (self enqueue-ing consumer), I feel the logic is the same (similar?) here?

First let me state some terminology to make sure we are all on the same page (I have doing this a lot lately).

Queued State Machine - A state machine that keeps track of which states it should go to in a queue.  And yes, I would consider the JKI State Machine a form of the QSM.

 

Queued Message Handler - A loop that uses a queue to recieve messages from other processes.  These messages are processed immediately and then the queue is checked again.  There was an argumentdiscussion over on LAVAg about dropping the 'Q' from this acronym since many did not use a Queue for the message transport (Notifier, User Event, etc, you can now add Channels).  So I will just call it a Message Handler (MH).

 

My opinions:

A state machine should be in full control of its states.  No other process should have access to the state queue.  But a well organized SM will have a state for checking for commands/messages (I like to use the Idle state for this).  The SM can react to those messages how it sees fit.  And those messages should be from another Queue or User Event.

 

A MH is quite dumb in the fact that it just does exactly what it was told (ie gets a message, does whatever reaction, and goes back to waiting for a message).  Any state it maintains is very minimal.

 

Now for the grey area:

I like to tweak the MH by using a timeout case to do something repeatedly, such as constantly reading a serial port.  This is making it closer to a SM, but not really.  It is still just reacting to a message.  A message told the MH to start taking data.  So the MH will check for messages and if nothing comes it, it does the "No Message" action of taking data and right back to checking for a message.

 

So how is this different from enqueuing a "Read" message inside of the MH?  If you add a message to the message queue, it will sit in there.  You have to keep track of if there is something still in the queue when you are told to stop taking data.  So you flush the queue, right?  Well, what if another message came in right before you flushed the queue?  You now have to add checks for that.  So this is turning into a big giant mess just to stop a read.  With the timeout method, I just set the timeout to -1 and it is done.

 

Some final thoughts:

If you have a process that needs to do ONE thing repeatedly while recieving messages from who knows where, use a MH with a timeout capability.  If you will be cycling through a lot of things for a single message, you need a SM with a state to check for more messages.  I find using a queue to hold the states work very well here since you can set an order to the states to go to.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 2 of 17
(10,429 Views)

Blokk,

     Thanks for starting this new thread.  Too bad we can't move my (probably overly-long) discussion of the Channel Messenger Hander in here.

 

     Blokk -- you asked "Is there no such danger as in the case of QSM explained before (self enqueue-ing consumer), I feel the logic is the same (similar?) here?"  I'm not sure that I completely understand where the "danger" lies (maybe because I try to "prevent trouble").  This may get into Crossrulz's careful distinction between a Message Handler and a State Machine -- he wrote "A state machine should be in full control of its states.  No other process should have access to the state queue.".  To me, that means that the State Machine, which is the "Consumer" of the SM's Queue, must also be the (main) Enqueuer of the States.  This is certainly the situation in the "Classic" State Machine, where the States are held in a Shift Register, with the Next State being put onto the Shift Register when the current State's Case ends.

 

     I appreciate Crossrulz's careful distinction between a Message Handler and a State Machine.  I confess that (as one of my students pointed out to me) my use of Terminology is a little sloppy at time -- I tend to use something that I think falls somewhere between the rigorous definition of the two.  Some of my "States" are "Remember this Value entered from a change to a Front Panel Control", where the Messenger's Data is saved on a Shift Register, while other States might be more "action" oriented, enqueing the next State to be done when this State finishes.  Since I'm (now) using Channels, I cannot "Enqueue at Opposite End" to create a "High Priority" input (when I asked, it was explained to me that this was a Bad Idea and could cause Race Conditions), so I try to design things to allow me to break out of a State Machine "loop" by having the State Machine's decision of What State To Do Next be another State Variable (I'm explaining this poorly -- I think I did a better job in the original post, here.)

 

The point of my previous post (referenced in the previous sentence) was the advantages I found in using the new Channel "pipes" (it seems strange to call them "Wires") for asynchronous communication among parallel loops.  One strong point that I didn't mention was that many Channels have very robust "Shutdown" mechanisms that greatly simplify the orderly termination of interacting parallel loops without such strange mechanisms such as releasing a Queue in one loop to trigger a Queue Error in another, or creating a Notifier just to send a Stop message to a loop.  With Channels, a Channel Writer can tell all of the Channel Readers that the "Channel is now closed" -- when it does this, the Writer (in the Producer) can safely exit, and when the Reader (in the Consumer) "gets the message", it can also safely exit.  There is no separate "Release" needed (nor is there any "Obtain", for that matter).

 

Bob Schor

Message 3 of 17
(10,421 Views)

Thank you both the replies! Right now I just have no time, but until the weekend I will find to read them through, and try to digest! So you might expect some more questions later on 🙂

 

Besides, I agree with the importance of using proper terminology. This is one of my problem when I try to understand explanations from expert LV programmers here in the forum or elsewhere: the language barrier is just one thing, but the other is that I have never studied programming in a formal way (university, etc.). So often I use wrong or not 100% correct wording, or do not understand exactly what the other tries to explain. But I try my best to improve 🙂

0 Kudos
Message 4 of 17
(10,409 Views)

It took me a while to find some links to old threads so I do not repeat myeslf.

 

These three links have some of my thoughts.

 

Link 1

 

Link 2

 

Link 3

 

Of particular interst is this thread where Daklu ( David, I believe he is the father of the Actor Framework)  was trying to document a QSM.

 

In the end I belive he accepted the idea the transitons of a QSM can not be defined in a closed form. This idea dovetails with what Tim was saying about defining transtions.

 

I am not sure if it is mentioned in any of those threads I linked there is another negative for the QSM that I bleieve was originally mentoined by Rolf where he pointed out the contents of the queue itself is hidded and with out previewing the queue, you really do not know what is in the queue and the oder of those items.

 

Re: Jeff''s Wire (aka channels...)

 

I have not loaded up 2016 so all I can say is...

 

"An amorphophallus plant by any other name, still stinks." (forgive me W. Shakespeare)

 

Ben

 

PS If you are even in the mood to research an idea when nobody is around you can go to my tag cloud found here and search for key words. I tried to used associated words and phrase that will let me find my way back to old thread with good info.

 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 5 of 17
(10,404 Views)

While ai am in the midst of a one-man dog-pile...

 

In this thread the questioner indicated the the serial nautre of the QSM he is using may have been slowing down his updates.

 

This reminded me that there is a paradigm shift that is helpful when moving from single threaded application to the parallel processing model of LabVIEW.

 

"Back in the day" when I was coding in BasicA, I had structure my code to handle all of the work that needed done. So my main loops would check on everything in every iteration. It was valid for that environment but hardly ideal and it also mde the code harder to support becuase while investigating one area of the application the code wold have to jump off to somewehre unrelated and then get back to where I was working.

 

An analogy that may help illustrate my point.

 

Say I have a small company that makes some widget. At first I could run the entire place myself running from station to station check ing each machine to keep it producing.

 

If I gear up and try to produce more than I can keep up with due to one of the steps be slow and time consuming, I wil be limited by the slowest step in my process.

 

So what I do?

 

Hire an assistant to focus on the slow step and then I can take care of the remaining stuff.

 

Say I gear up again and again find myself limited by my own capacity. I an jump to the endo f the story and recognize that if I hire people to specialize and focus on a single step in the work that needs done I can run the opperation as fast as possilbe being limted then by the speed of the slowest step. In that model I have a bunch of lower tech employees all doing a single opeartion well. Noe of them are distracted by the other work being done in the plant.

 

Taking that idea over to LabVIEW...

 

When designing the architecture of my applications, I often spend time thinking through the requirements an the work as a factory with multiple employees each doing their job and interacting where and when needed. These are latter traslated into libraries or loops for each of the requirements. So when I have a problem with a part of an application I am looking at code associated with that functionality with minimal distraction by the other stuff.

 

Closing out this diatribe...

 

A QSM can morph into a one-armed-paper-hanger with a few changes and additons.

 

A parallel processing model is like deploying an army of specialists.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 6 of 17
(10,339 Views)

Strangly enough, (or perhaps it is serendipity) I ran across these sources today.

 

I'm not going to summarize them but, let a few guys say their own piece.  Which I found rather enlightening.

Jon has a good inside-out take on the subject that I think addresses the oroborus issue Just give me the data I know what to do!

Dimitry explains Why

 

I Still have a few strands of duct-tape in place holding my brain together.  And AN SHRUBBERY to unpack! its here!


"Should be" isn't "Is" -Jay
Message 7 of 17
(10,317 Views)

Thanks for all the links and interesting readings! Now you guys just filled my reading Queue faster than I can process through, but I try my best to starve this snake 🙂

Hmm, LVOOP...still did not start to dig in. A few years ago started the selfpaced online training, but that example project just did not switch into my brain, stopped learning halfway 😞

 

By the way, I am so dumb 🙂 I initiated this discussion about the queued state machine ( message handler?, forever confused about terminology), and how I like it, and I just totally forgot an early time when this snake bit me too! I just had a simple Daq loop to process commands from the GUI loop, and beside this daq loop was self-enqueueing "Measure!" commands at two cases: inside the "Initialize" case, and inside the "Measure!" case. Ok, later on I started to add more features/commands to the design: like zero-set multimeter, enable output, etc. I made these commands priority, so they went into the front of the Queue. Ok, just without further thinking, i also added a "Measure!" command into the Queue after executing such special non measurement task. My brain just said: "after executing an extra case, we need to go back to the "Measure!" case!" No? Oh NO! 🙂 My code just started to pile up "Measure!" commands. But since all the other commands were priority, this behaviour was not immediately seen...later on i needed to add a Queue status checker to see how many elements I have in the Queue during runtime, to realize my dumbness :)))

 

So yes, the snake bit me, and since that I was always very careful, so much, that i even forgot about this happened once 🙂

Message 8 of 17
(10,300 Views)

@Blokk wrote:

...

 

So yes, the snake bit me, and since that I was always very careful, so much, that i even forgot about this happened once 🙂


Thank you for offering to support my warnings. My quest as has been to spare other developers the curse of the worm oroborose. Sorry I did not warn you eraly enough.

 

Some more trivia to fill in the hsitorcial blanks...

 

G-Story Time

 

Prior to LV 5 ( Ithink it was 5) LV was single threaded. regadless of hwo we structured our code, it all got serialized as the ocde segements were schedule to get acccess to the single CPU of the time. So like it or not, everything had to end up waiting for the slowest thing no matter what we did.

 

At that time VI Engineering developed the first version of LabVIEW Advanced Course. It was in that book (I did not take their course but my boss at the time was teaching it so I have his course manual) that the QSM was taught and encouraged. It was alos that book from which I learned about Action Engines (if you read my nugget on Action Engines, you will see I gave VIE credit).

 

One of our customers took that course and being a old-time push-and-pop off othe stack guy, he took to that design pattern like it was an old friend. But the design patern eventually failed him about the time he had some many cass in the QSM you had to scroll through the case options to work with the code. He eventually threw up his hands and turned it over to us to support and rewrite it.

 

Spoiler

 

[Set Mode Proud Poppa mode = True]

 

 

My rookies eventually ended up winning the "Graphical System Disgn Achievement Award - NI LabVIEW FPGA Innovation Award" and was also a Finalist in the energy catagory.

 

[Set Proud Poppa mode - False]

 

 

 

So the Worm had its day in the  bathing in the sunlight, and for simple application it is still valid. But if you really need to do multiple things at the same time, look elsewhere for a good design pattern.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 17
(10,285 Views)

@JÞB wrote:

Strangly enough, (or perhaps it is serendipity) I ran across these sources today.

 

I'm not going to summarize them but, let a few guys say their own piece.  Which I found rather enlightening.

Jon has a good inside-out take on the subject that I think addresses the oroborus issue Just give me the data I know what to do!

Dimitry explains Why

 

I Still have a few strands of duct-tape in place holding my brain together.  And AN SHRUBBERY to unpack! its here!


I think you should expand on why and how that bolg post fits in here Jeff. Please "throw us a bone".

 

(smiley-wink)

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 10 of 17
(10,283 Views)