LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Queues: Unaccounted Extra Element Upon Release Queue

Solved!
Go to solution

Hello,

 

I've been playing around with the queue event state machine notion combined with a functional global variable, and can't seem to get passed a certain bug (I've searched but no results came up with the same problem).

 

I've attached a simple VI and subvi. The main VI consists of a producer and consumer loop, event structure in the producer loop, case structure in the consumer loop to handle processes

 

The problem I am facing is that the consumer loop goes through an extra iteration upon stopping the producer loop and releasing the queue. Further, during this extra iteration the dequeue element spits out an extra item that I can not track down. The queue should be empty, so where does this extra element, which is always 0 ("Initialize") in this case, come from? I've tried adding a "Read" to the stop event, which does enqueue a "Read", but the extra (last) element is always 0 ("Initialize").

Download All
0 Kudos
Message 1 of 12
(3,682 Views)
Solution
Accepted by topic author srv535

You are stopping your loop by destroying the queue reference. When you destroy the queue reference, the dequeue operation dequeues the "default" value of the queue data type, which for your case is 0.

 

You can avoid writing to your FGV by wiring a error case structure if you want to keep the same structure.

 

See below.

 

mcduff

 

Snap57.png

Message 2 of 12
(3,674 Views)

Thanks for the quick reply! Did not know that the queue releases the data type itself at the default value after the reference is destroyed.

 

In this case, to maintain the same structure would I implicitly stop the consumer loop instead of wiring the error out of the dequeue to stop?

 

edit: attached my alternative that maintains structure.

Download All
0 Kudos
Message 3 of 12
(3,660 Views)

@srv535 wrote:

Thanks for the quick reply! Did not know that the queue releases the data type itself at the default value after the reference is destroyed.

 

In this case, to maintain the same structure would I implicitly stop the consumer loop instead of wiring the error out of the dequeue to stop?


If you are referring to adding a stop or using a local variable, I would recommend against it.

 

Add an "Exit/Stop" State to you Enum, then stop your consumer when it gets the command. See below. Also make your enum a type-def. Then destroy your queue from the consumer loop.

 

mcduff

 

Snap58.png

 

0 Kudos
Message 4 of 12
(3,656 Views)

From the examples I've seen, users always seem to release queues upon stopping their producer loop. Is it better practice to release queue when stopping the consumer loop?

 

alt.png

0 Kudos
Message 5 of 12
(3,652 Views)

That is up to you.

 

Consider your producer is much faster than your consumer, if you destroy the queue when the producer is finished (the consumer is still working) you will lose data. Does your application depend on this data, I do not know, that is why I said it is up to you. But you will lose data/states etc, if you destroy the queue before the consumer is finished.

 

mcduff

0 Kudos
Message 6 of 12
(3,646 Views)

@srv535 wrote:

From the examples I've seen, users always seem to release queues upon stopping their producer loop. Is it better practice to release queue when stopping the consumer loop?

Yes!!  (IMHO).  Think about it --

  • "Information" travels from Producer to Consumer.  The Producer has the data, and the Producer also knows when there's no more data coming.
  • When the Producer knows there's no more data coming, it exits.
  • How does the Consumer know there is no more data coming?  The technique I use is to have the Producer, when it exits its loop, send a "Sentinel" (a unique value, such as an empty String or an empty Array).
  • The Consumer, when it gets each item from the Producer, checks to see if it is the Sentinel (in the example above, it has an "Empty String?" or "Empty Array?" function guarding a Case Statement).  If so, there's no data (so skip any processing) and there's no more data coming (so exit the loop).
  • When the Consumer exits the loop, the Consumer releases the Queue.  It is guaranteed to be safe, as the above chain of events means (a) the Producer has exited, hence (b) the Producer will not send anything more on the Queue, so (c) the Queue is no longer needed.

Bob Schor

 

P.S. -- I learned about Sentinels (and their use in Queues) a few years ago in a book on "Advanced Fortran Programming" (that's not the title, but a description of the content).

0 Kudos
Message 7 of 12
(3,629 Views)

I do remember using the queue producer/consumer structure for simply recording and processing data on one project as the processing was much slower than recording (placing the data acquisition and processing in one loop was extremely slow). I was under the impression that the consumer loop continued even after the producer loop stopped until the queue was empty. This is why I placed Flush Queue before Release Queue in this example so that we empty the queue before releasing, thus stopping the consumer loop immediately.

0 Kudos
Message 8 of 12
(3,621 Views)

@srv535 wrote:

I do remember using the queue producer/consumer structure for simply recording and processing data on one project as the processing was much slower than recording (placing the data acquisition and processing in one loop was extremely slow). I was under the impression that the consumer loop continued even after the producer loop stopped until the queue was empty. This is why I placed Flush Queue before Release Queue in this example so that we empty the queue before releasing, thus stopping the consumer loop immediately.


The "flush" occurs at that function, all the elements in the queue are released there. You can check by wiring up an array to that output by the queue. Once flushed the data is gone, your dequeue will not see it. (You would flush your Exit/stop command, so your bottom loop would not stop unless it was to stop on error.)

 

mcduff

0 Kudos
Message 9 of 12
(3,616 Views)

Its "One of those things" computer science academics an esoteric programmers disagree on.

 

Purists will rant that releasing the queue in the producer is technically better practice.   I won't argue that point but, always use an exit message myself and dump the queue after both loops finish.  Practical mysticism that may make the compiler's job a bit harder costing a few nanoseconds of CPU time.  Or not...  certainly not impacting anything that I am likely to use LabVIEW for. 


"Should be" isn't "Is" -Jay
0 Kudos
Message 10 of 12
(3,612 Views)