LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Recommended way of wiring queue RefNum?

I've seen two ways to wire the Queue Refnum in an event-based producer-consumer environment. This is from the LabVIEW template:

lvtemplatew1.png

 The queue reference is given into the loop by simple tunnel and used after the loop is done by simply wiring around it. The following snippet is showing another way:

w2.png

 This time, the queue reference is wired via a shift register and after the last loop iteration forwarded to the queue release.

 

Are there any differences between both approaches or downsides? Obviously the second way involves more wiring making the diagram less readable in my opinion. Thanks for the clarification!

0 Kudos
Message 1 of 13
(677 Views)

You've hit it already. Less opportunity for forgetting to wire in the top example, since tunnels on event structures default to not needing to be wired and then *poof* away goes access to the queue reference.

 

I tend to avoid wiring through structures for reference types just to save myself some wiring. If I have direct control over when a loop will terminated (that is, no error into the stop terminal) then I'll wire through but only wire up the output on the terminating case and don't use a shift register.

~ The wizard formerly known as DerrickB ~
Gradatim Ferociter
Message 2 of 13
(662 Views)

I take the general approach that anything that goes in a shift register in a loop is something that could change from iteration to iteration.

 

Unless you have multiple queues that you're switching between, or creating and destroying them as you go, a queue reference never changes and is therefore something that shouldn't go in a shift register.

 

One small other thing is that in either of those situations, I would recommend that the consumer loop be the one that triggers the closing of the reference as a general rule.  If the producer loop finishing destroys the reference, then there's a chance that there will be unexecuted consumer loop actions that never happen.  If that's what you want, enqueue a "stop" action to the front of the queue to get the same effect.  Some producer/consumer loops treat the destruction of the queue as a "stop" action but that can lead to skipped queue elements, and it's not hard at all to just add "stop" as one more action.

Message 3 of 13
(638 Views)

In regard to destroying the reference. Here is something that might help down the road.  You'll notice there is a condition where the producer loop might complete while the consumer is still running.  When the producer is stopped/finished, the reference is destroyed.  The "side-effect" of destroying the reference while the consumer is still running can be used to the programmers advantage.  The VI waiting in the consumer will generate an error once the reference to it is destroyed.  The error output of the VI can be wired and used to stop the consumer loop.  Kind of a handy "feature."

0 Kudos
Message 4 of 13
(581 Views)

@BigApple0 wrote:

In regard to destroying the reference. Here is something that might help down the road.  You'll notice there is a condition where the producer loop might complete while the consumer is still running.  When the producer is stopped/finished, the reference is destroyed.  The "side-effect" of destroying the reference while the consumer is still running can be used to the programmers advantage.  The VI waiting in the consumer will generate an error once the reference to it is destroyed.  The error output of the VI can be wired and used to stop the consumer loop.  Kind of a handy "feature."


But the big disadvantage is that anything that was in the queue isn't there any more, meaning data loss.  Maybe this is fine for you... or maybe you are wondering why you are missing the last few points of data... or even worse, maybe you don't even realize you are missing the last few points of data.

 

To avoid potential data loss, always send an explicit "exit" message to the consumer.  I used to do what you mentioned here until someone told me what I just told you.

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 5 of 13
(558 Views)

@billko wrote:

@BigApple0 wrote:

In regard to destroying the reference. Here is something that might help down the road.  You'll notice there is a condition where the producer loop might complete while the consumer is still running.  When the producer is stopped/finished, the reference is destroyed.  The "side-effect" of destroying the reference while the consumer is still running can be used to the programmers advantage.  The VI waiting in the consumer will generate an error once the reference to it is destroyed.  The error output of the VI can be wired and used to stop the consumer loop.  Kind of a handy "feature."


But the big disadvantage is that anything that was in the queue isn't there any more, meaning data loss.  Maybe this is fine for you... or maybe you are wondering why you are missing the last few points of data... or even worse, maybe you don't even realize you are missing the last few points of data.

 

To avoid potential data loss, always send an explicit "exit" message to the consumer.  I used to do what you mentioned here until someone told me what I just told you.


I have the general rule (applies 99.8% of the time) that the consumer is the one in charge of the queue reference.  The consumer needs to be told when to stop and it can then destroy the queue when it completes.


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
0 Kudos
Message 6 of 13
(537 Views)

@crossrulz wrote:

@billko wrote:

@BigApple0 wrote:

In regard to destroying the reference. Here is something that might help down the road.  You'll notice there is a condition where the producer loop might complete while the consumer is still running.  When the producer is stopped/finished, the reference is destroyed.  The "side-effect" of destroying the reference while the consumer is still running can be used to the programmers advantage.  The VI waiting in the consumer will generate an error once the reference to it is destroyed.  The error output of the VI can be wired and used to stop the consumer loop.  Kind of a handy "feature."


But the big disadvantage is that anything that was in the queue isn't there any more, meaning data loss.  Maybe this is fine for you... or maybe you are wondering why you are missing the last few points of data... or even worse, maybe you don't even realize you are missing the last few points of data.

 

To avoid potential data loss, always send an explicit "exit" message to the consumer.  I used to do what you mentioned here until someone told me what I just told you.


I have the general rule (applies 99.8% of the time) that the consumer is the one in charge of the queue reference.  The consumer needs to be told when to stop and it can then destroy the queue when it completes.


Your explanation was so much more elegant than mine.  Yes, this is what I was trying to get across.  Consumer loop exits gracefully, destroy the queue after loop exits.  If you want to be even more thorough, you can merge the errors from producer and consumer loops before destroying the queue just to make certain everyone's absolutely ready to have the queue destroyed.

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 7 of 13
(520 Views)

@billko wrote:
If you want to be even more thorough, you can merge the errors from producer and consumer loops before destroying the queue just to make certain everyone's absolutely ready to have the queue destroyed.

From a cohesiveness aspect, that only makes sense when dealing with the simple Producer/Consumer and everything in on the same block diagram.  Once you start going into "actors" or "message handlers" (really they are the same concept), you really want to use libraries to create these boundaries.  Part of that setting the boundaries is having the queue lifetime on the consumer VI.  This is something Actor Framework did extremely well.

 

At this point, it is more of a readability and SOLID issue than functionality.


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
0 Kudos
Message 8 of 13
(512 Views)

@Kyle97330 wrote:

I take the general approach that anything that goes in a shift register in a loop is something that could change from iteration to iteration.

 

Unless you have multiple queues that you're switching between, or creating and destroying them as you go, a queue reference never changes and is therefore something that shouldn't go in a shift register.

 

One small other thing is that in either of those situations, I would recommend that the consumer loop be the one that triggers the closing of the reference as a general rule.  If the producer loop finishing destroys the reference, then there's a chance that there will be unexecuted consumer loop actions that never happen.  If that's what you want, enqueue a "stop" action to the front of the queue to get the same effect.  Some producer/consumer loops treat the destruction of the queue as a "stop" action but that can lead to skipped queue elements, and it's not hard at all to just add "stop" as one more action.


There is one issue with this approach and that is if your wire a reference through a For loop using just a terminal and need the reference output from that For loop you will run into problems if the loop executes 0 times. If the For loop doesn't execute, such as the iteration value if 0 or the array driving the loop is empty, the reference will be lost. The output from the For loop will be an invalid reference, not what you wired into the loop. 



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 9 of 13
(505 Views)

@Mark_Yedinak wrote:

@Kyle97330 wrote:

I take the general approach that anything that goes in a shift register in a loop is something that could change from iteration to iteration.

 

Unless you have multiple queues that you're switching between, or creating and destroying them as you go, a queue reference never changes and is therefore something that shouldn't go in a shift register.

 

One small other thing is that in either of those situations, I would recommend that the consumer loop be the one that triggers the closing of the reference as a general rule.  If the producer loop finishing destroys the reference, then there's a chance that there will be unexecuted consumer loop actions that never happen.  If that's what you want, enqueue a "stop" action to the front of the queue to get the same effect.  Some producer/consumer loops treat the destruction of the queue as a "stop" action but that can lead to skipped queue elements, and it's not hard at all to just add "stop" as one more action.


There is one issue with this approach and that is if your wire a reference through a For loop using just a terminal and need the reference output from that For loop you will run into problems if the loop executes 0 times. If the For loop doesn't execute, such as the iteration value if 0 or the array driving the loop is empty, the reference will be lost. The output from the For loop will be an invalid reference, not what you wired into the loop. 


Just to expand a little on that thought, the same thing happens to anything that "feeds through" the FOR loop.  If it iterates zero times, you get the default for the datatype out, unless it's in a shift register, which "carries" the original value to the "other side".

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 10 of 13
(493 Views)