LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Queue are blocking calls.

Solved!
Go to solution

Queues are blocking calls.

Whether it means enqueue and dequeue Will never going to execute at the same time, right?

 

Can anybody please help me understand this.

 

Hemant

0 Kudos
Message 1 of 19
(3,861 Views)

If you have a limited queue size the Enqueue can get stuck waiting for a slot to fill, is that what's happening?

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 2 of 19
(3,855 Views)
Solution
Accepted by LV_COder

Both Enqueue and Dequeue function have a timeout input. If you wire any non-negative number to this input (say N), these function will wait N milliseconds at maximum before exiting, so they won't block. Of course they may not execute the actual enqueue or dequeue operation: it's up to you to manage this situation and retry the operation at a later time.

Paolo
-------------------
LV 7.1, 2011, 2017, 2019, 2021
Message 3 of 19
(3,839 Views)

What a "blocking call" means is that if there is no input, the function doesn't run, and effectively "blocks" the execution of any loop containing it.

 

This situation comes up with Producer/Consumer Designs using a Queue to send data from Producer to Consumer.  It is easier to understand for the Consumer, which is generally coded as a Dequeue (of, say, a Waveform) followed by code to process the data (which could take time, depending on the processing).  If the Dequeue is the first function in the Loop (the usual case), the loop will "block" (that is, not run, not take any CPU cycles) until data is put on the Queue (by the Producer).  At that point, the Consumer "unblocks", dequeues the data, and (using normal DataFlow) gives it to the Processing Code.

 

The same thing can happen with Enqueue in the Producer loop -- until data is presented to it, the Enqueue function will "block", not run, and any code inside the loop that "follow" it via Data Flow principles will also not run.  A typical Producer is sending DAQmx data from a DAQmx Read to a Consumer loop.  A DAQmx Read "blocks" until it has data to present to the Queue, so even if it wasn't connected via the Error Line (the usual "good programming" situation), the Enqueue function will "block" (and not run) until it receives it Data In.

 

OK, so now that you know the "Rule", you need to know the important Exception (and understand why it is there, and how to use it).  Suppose we have a Producer as in the previous paragraph, and you execute (somewhere) a DAQmx Stop Task.  This means there will be no more data coming to the Enqueue Element function, and it will block its While loop, preventing the loop for exiting even if the Stop indicator is wire to True.  Oops!  Both Enqueue and Dequeue have a Timeout input, set by default to -1 (which effectively means "Never Time Out").  If you want to guard against the above situation, you can set the Timeout to, say, 1000, meaning "If I've had no data to send in the last Second = 1000 msec, I should check to see if, or just assume that, it is time to quit".  Just as there is a Timeout Input on these functions, there is a "Timed Out?" boolean output that is True if the function did, indeed, time out.

 

Best practice is to structure your code so that loop shutdown can be managed without needing the "Timeout" Exception, but it is there as a backup when you need it.

 

Bob Schor

 

 

Message 4 of 19
(3,838 Views)

Bob_Schor wrote:

Suppose we have a Producer as in the previous paragraph, and you execute (somewhere) a DAQmx Stop Task.  This means there will be no more data coming to the Enqueue Element function, and it will block its While loop, preventing the loop for exiting even if the Stop indicator is wire to True.


This is not correct.  The Enqueue just uses whatever data is in the wire going to it.  If you stop the DAQmx task, then the DAQmx Read will return an error and an empty waveform.  Assuming the error wire is not wired up (bad practice), the Enqueue will still add the empty waveform into the queue.  It is not blocking the loop.

 

Where the Enqueue Element will block is when you have a fixed sized queue and the consumer is being slow and not getting the data off quick enough.  This will cause the queue to fill up and the Enqueue Element will wait for room in the queue to open up.


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 5 of 19
(3,814 Views)

As usual, Crossrulz is correct, and my particular example was flawed.  So let's change the DAQmx Read to be a "triggered A/D", and you stop the task generating the triggers, "stalling" the DAQmx Read.  It never completes, it never passes data to the Enqueue function, it never sets its Error Out (whether it is wired, as I noted it should be, to the Enqueue function or not), and the Enqueue is "starved" for input, and blocks.

 

Bob Schor

0 Kudos
Message 6 of 19
(3,811 Views)

@Bob_Schor wrote:

As usual, Crossrulz is correct, and my particular example was flawed.  So let's change the DAQmx Read to be a "triggered A/D", and you stop the task generating the triggers, "stalling" the DAQmx Read.  It never completes, it never passes data to the Enqueue function, it never sets its Error Out (whether it is wired, as I noted it should be, to the Enqueue function or not), and the Enqueue is "starved" for input, and blocks.


Just to be clear, it is not the Enqueue Element that is blocking.  It is the DAQmx Read that is blocking everything downstream from running, including the Enqueue Element.


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 7 of 19
(3,791 Views)

Hmmmm....

 

The term "blocking" may have diverse meanings.

 

This article about the Root Loop talks about how the root loop will block code execution.

 

I have been told that queues are "blocking" in that they can be prevented from running under the right/wrong conditions. Not knowing the internals of LV but having some insight into how queues used to be implemented in hardware there were machine instructions called "insert into Queue Interlocked" where only one CPU could access the queue at a time via a mutual exclusive flag in the hardware.

 

Now pushing my knowledge a bit too far...

 

Enquue and Dequeue have to touch a shared data structure that is ued to maintain the queue so I can see how those can be "blocking".

 

Is it the Notifiers that allow previewing same with out blocking?

 

In general blocking operators can impact determinism and should be avoided in Time Critical loops.

 

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 8 of 19
(3,762 Views)

Back in LabVIEW 6.1 RT it was considered "the right way" to use a Action Engine set as sub-routine priority and then choose the right-click option "skip if busy" to be able to avoid the Time critical loop from experiencing jitter. A Boolean True could be used to indicate if the call executed or not. The skipped sub-VI would return the default value if the VI was skipped.

 

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 19
(3,750 Views)

Thanks for replying and sorry for late response. 

But Whether LabVIEW enqueue and dequeue functions execute at the same time (simultaneous, parallel ) as they are shared resource.

Or at a give point only one function will execute enqueue or dequeue.

 

 

0 Kudos
Message 10 of 19
(3,708 Views)