LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

producer -consumer code with several variables (types)

To be honest I do not like using timeout for the DAQ loop dequeue function in such case, because it makes the timing of this consumer loop "multi-place dependent". The total loop iteration depends on what you wire to this timeout and the elapsed time during the DAQ action. Of course, you can set the dequeue to time out immediately, but this can cause problems when you do not want to have this loop always running, and just process some commands infrequently for example. Using timeout makes the design less scalable for future changes.

 

I think using a self-queueing method is just superior over using timeout, since you decide when a new command is inserted into this Queue..

 

singlecase.png

 

 

0 Kudos
Message 21 of 47
(1,964 Views)

So, that's where I am getting confused.

 

Here is my version of the VI. I've got a DAQ to add (only acquiring data, continusously aquicring) and he logging system.

 

The case "READ" is where I don't get why I should not use the timeout event in the first loop:

- there are the data I want to produce and display

- I would enqueue the DAQ to add and those data to dequeue them in a third loop

 

For the logging system, I beleiveI will have to enqueue wihtin the "big" loop and create a third one where I dequeue.

 

Am I on the right way? (please ignore the badly wired cables)

0 Kudos
Message 22 of 47
(1,957 Views)

You should not use your event loop to produce data. Use it only to send user commands to the second loop. The second loop is producing data, and sending it to a third loop for display and logging.

0 Kudos
Message 23 of 47
(1,955 Views)

@Blokk wrote:

....

I think using a self-queueing method is just superior over using timeout, since you decide when a new command is inserted into this Queue..

 

singlecase.png

 

 


No Sir! Don't like it (Mr. Horse)

 

that is just another name for the Worm Oroborose of software desings. Like a dragon eating its tail it is best kept starved or killed completely.

 

I have made a lot of money over the years unwinding the tangled knot of QSMs that grew out of control and the next thing you know, Safety concerns go wanting and parts under a million pounds of force start breaking.

 

They were very popular with "old-time" programmers that thought in terms of pushing on to a stackning and popping off or "go-sub". But we need only look as far a Dhijkstra to learn that "goto" introduces chaos which is a bad thing when controlling hardware.

 

What you are effectively doing with code like that is is using a state like it is a sub-routine. So create a sub-VI and call it!

 

Yes you can get away with it if you know the dangers and only push one thing at a time but eventually some other poor soul will find themselves looking a tthe example you left them with and add a second and then a third and then a disaster that looks like a gordian knot!

 

No Sir! don't like it. (Mr Horse)

 

Ben

 

Spoiler
I will be rewriting one of those gordian knots when I get back from vacation in January.
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 24 of 47
(1,953 Views)

Hmm, i did not consider this vulnerability of this design so far, thanks to highlight it! I have to think it over, and reread your post, i am not a native English speaker, haha 🙂

Anyway, if i use such solution, i could put a large red comment there: "Only enqueue the Daq task command at two single places: at the Init case, and at the Daq task case!" 🙂

Message 25 of 47
(1,950 Views)

@Blokk wrote:

Of course, you can set the dequeue to time out immediately, but this can cause problems when you do not want to have this loop always running, and just process some commands infrequently for example. Using timeout makes the design less scalable for future changes.


That is why I keep the timeout in a shift register.  Then I can change it to -1 (wait forever) if we do not need to be running or 0 (or whatever rate you want) when we are running.  And the message coming through the queue will still always be caught.


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 26 of 47
(1,936 Views)

@Blokk wrote:

Hmm, i did not consider this vulnerability of this design so far, thanks to highlight it! I have to think it over, and reread your post, i am not a native English speaker, haha 🙂

Anyway, if i use such solution, i could put a large red comment there: "Only enqueue the Daq task command at two single places: at the Init case, and at the Daq task case!" 🙂


Yeah, there ase some problems with that code

Do read some of the "Blue" comments. 

Capture.PNG


"Should be" isn't "Is" -Jay
0 Kudos
Message 27 of 47
(1,936 Views)

@JÞB wrote:

@Blokk wrote:

Hmm, i did not consider this vulnerability of this design so far, thanks to highlight it! I have to think it over, and reread your post, i am not a native English speaker, haha 🙂

Anyway, if i use such solution, i could put a large red comment there: "Only enqueue the Daq task command at two single places: at the Init case, and at the Daq task case!" 🙂


Yeah, there ase some problems with that code

Do read some of the "Blue" comments. 

 


Yes, you are totally right, but I only used this built-in template to show the "self-enqueue" mechanism, that part intended to be the only relevant info. Obviously this Producer/consumer built-in template needs many changes and fixes regarding to error handlind, etc. Also a User Event can be handy to send information "backward"...

 

edit: and I have to admit, that QSM with self-enqueue-ing is somehow just so tempting, there is some beauty in the picture when a snake bites into its own tail 🙂 Or feels as cool as Baron Munchausen pulling himself out from the swamp 🙂

 

Muenchhausen_Herrfurth_7_500x789.jpg

Message 28 of 47
(1,927 Views)

that QSM with self-enqueue-ing is somehow just so tempting, there is some beauty in the picture when a snake bites into its own tail.

 

However, Ben's concerns are very real!  Some future developer is going to put venom in that snake.  Then you have busted code that someone else "Patched" with workarounds and somehow got to work by idiosyncratic means such as; enforcing a race condition (I've seen that happen)!  It is a weakness of any language based on dataflow that anything that breaks dataflow requires that the Actor must have a referance to the means to break dataflow.  That is, If I can respond to the event I can also generate that same event and if I can dequeue from a queue nothing stops me from enqueueing to the same queue.  Only proper training can prevent such abuses.  Many are not properly trained (But thats why we get Kudos!)


"Should be" isn't "Is" -Jay
Message 29 of 47
(1,915 Views)

Well, since we are talking Producer/Consumer with multiple loops, Queued Message Handlers, and LabVIEW 2016, let me suggest the Channel Message Hander (I just made up that term) based on Channel Wires introduced (officially) in LabVIEW 2016 (I'm a real fan!).

 

Here is an example of four parallel loops, two running a Channel Message Handler (meaning that the loop is controlled by data flowing through a messenger channel, shown in the diagram as pinkish pipes) and two running as a "conventional" Producer/Consumer, connected by a Stream Channel (pink pipe below bottom two VIs labelled Producer and Consumer).

Channel Message Handler.png

There are two Messenger Channels at work here (all using pink pipes).  One connects the Event Loop on top with the main State Machine (big loop in the middle), and has connections to sub-VIs coming out of the tops of the sub-VIs.  The other is the Channel going from the State Machine (from the sub-VI "Send Triax") sending Messengers to the Producer Loop shown as the small sub-VI below the main State Machine (inside is code looking somewhat like the main State Machine loop shown here).

 

Messengers are generated by the sub-VIs called "Send State", found in the Event Loop, just in front of the State Machine Loop, and inside the State Machine Loop.  In addition, a special Messenger Generator is the Error Handler VI -- if it is entered with an Error on the Error Line, it clears the Error and generates an Error State, with the (Error) contents of the Error Line as the Messenger's Data.

 

Shown here is the processing that takes place if the User pushes the Calibrate Button on the Front Panel.  This generates a Calibrate Button Event, which puts the Calibrate State on the State Messenger.  Note that while there are multiple Send State, there is only a single Receive State inside the State Machine.  When a Calibrate State is sent via Messenger, the code illustrated here runs.  It "does some stufff" (runs a Calibration inside a Front Panel), sets up some DAQmx Tasks, then starts the Producer/Consumer pair running by sending the first State, "Initialize", to the Producer via "Send Triax".

 

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.  When it starts running, it goes into a "Take a Sample" State, where a DAQ sample is acquired (in one instance, I take 10 samples at a time at 1KHz).  The way I handle looping is to save the Next State (typically "Take a Sample") in a Shift Register.  However, when Logic says "Time to stop Sampling", I simply call a "Stop Sampling" State that changes the Shift Register to put the "Done" State as the Next State to be called.  This State simply does nothing, stopping the State Machine from looping (until another Start Sampling State is received, of course).

 

This may sound complicated, but it really works very nicely.  I've done similar things with Queues, but find Channels much easier to use, easier to visualize, easier to explain, and despite the "thicker pipes", less "intrusive" on the Block Diagram than Queues (maybe because they "stand out").

 

One final thing to note is the very new Event Messenger Channel (the Blue Pipe) that enables User Events via Channels -- I use this specifically to stop the Event Loop in case of an Error Shutdown.

 

Bob Schor 

Message 30 of 47
(1,890 Views)