LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Does creating queue/enqueue/dequeue/release queue work inside an FGV

Solved!
Go to solution

I intentionally left my computer at work in order to force myself into some pad+pencil planning, so I can't test this. But I'm dying to know.

 

Can I make an FGV where the enum selects cases like "create/obtain", "enqueue","dequeue", and "release queue" to have the FGV make things easier? The main thing I'm uncertain about is whether the queue reference would immediately become invalid after creation since an FGV stops after a single pass of the while loop. 

 

Aside from convenience, it also seems like an easy way to ensure the queue is created/released in a single place. However, I'm also wondering whether this is a bad idea since I'd lose the event-like characteristics of having a dequeue with no time out in a loop that will actually be utilizing the data. I don't know, I'd like to hear comments on this vs using an FGV only for storing the reference, create, release functions.

0 Kudos
Message 1 of 6
(3,073 Views)
Solution
Accepted by DoctorAutomatic

The FGV is based on the idea of a shift register / feedback node to store data between executions of the FGV. So the while loop is simply a way to expose shift register terminals; a FOR loop with a fixed iteration of 1 would do the same thing. A feedback node with no looping structure also achieves the same goal.

 

The FGV (and all VIs for that matter) stay in memory until the VI hierarchy goes idle, typically when the top-level VI stops executing. So you can continue to call the FGV within the execution of the top-level VI and SubVIs and be confident that the shift register / feedback node storing your queue reference still refers to an actual queue reference up until the point that you explicitly close the reference (via your release option) or the top level VI goes idle at which point typically all contained references are released automatically.

 

Using a FGV for this is a simple way of sharing a queue without using wires on a block diagram. Like all design decisions it has some consequences though:

  • No wires means it is less clear that some of your SubVIs depend on the FGV to function. Having a wire implicitly communicates that your SubVI depends on this queue to do its job. This can become important in larger more complex applications.
  • You only get a single instance of the FGV to play with (by definition) so duplication is less flexible when you need multiple instances.
  • Since each FGV call is blocking you could unintentionally block callers of the FGV. For example - while one caller is waiting on a dequeue operation no other caller can try and execute an enqueue operation until that caller exits via timeout. It also blocks other useful concurrent operations such as Preview Queue operations where the caller only needs to view the top of the queue. AQ put a great deal of effort into ensuring that the Queue API is thread-safe in these scenarios.

In general, using an FGV is a way of capturing atomic operations on a single global object. When using them I would suggest questioning yourself as to whether any of the negatives above are deal-breakers.

0 Kudos
Message 2 of 6
(3,063 Views)

Hi Doctor.  Using an FGV with a case inside a while loop as you describe is a good way to go, I do exactly that frequently.  Just wire the queue refs out to shift registers on the while loop and you are all set.  You can always pass the timeout flag out of the FGV so that the caller can respond appropriately.

 

Matt

0 Kudos
Message 3 of 6
(3,057 Views)

I've long used something I call a "Wireless Queue", which is an Action Engine (what you call an FGV) with Obtain, Enqueue, Status, and Release functions, an Element In terminal, and a Queue Out terminal.  The first time I built this, I also had Dequeue as an Action -- bad idea, it blocked!  So when I want to Dequeue (in a single place!), I put a call to Status (to get me the Queue Out) outside the Dequeue's While Loop and bring the Queue into an interior "Dequeue" function, thus not blocking the Wireless Queue.

 

I use these much more rarely now, having largely replaced Queues with Channel Wires.

 

Bob Schor

0 Kudos
Message 4 of 6
(3,039 Views)

@tyk007 wrote:

The FGV is based on the idea of a shift register / feedback node to store data between executions of the FGV. So the while loop is simply a way to expose shift register terminals; a FOR loop with a fixed iteration of 1 would do the same thing. A feedback node with no looping structure also achieves the same goal.

 

The FGV (and all VIs for that matter) stay in memory until the VI hierarchy goes idle, typically when the top-level VI stops executing. So you can continue to call the FGV within the execution of the top-level VI and SubVIs and be confident that the shift register / feedback node storing your queue reference still refers to an actual queue reference up until the point that you explicitly close the reference (via your release option) or the top level VI goes idle at which point typically all contained references are released automatically.

 

Using a FGV for this is a simple way of sharing a queue without using wires on a block diagram. Like all design decisions it has some consequences though:

  • No wires means it is less clear that some of your SubVIs depend on the FGV to function. Having a wire implicitly communicates that your SubVI depends on this queue to do its job. This can become important in larger more complex applications.
  • You only get a single instance of the FGV to play with (by definition) so duplication is less flexible when you need multiple instances.
  • Since each FGV call is blocking you could unintentionally block callers of the FGV. For example - while one caller is waiting on a dequeue operation no other caller can try and execute an enqueue operation until that caller exits via timeout. It also blocks other useful concurrent operations such as Preview Queue operations where the caller only needs to view the top of the queue. AQ put a great deal of effort into ensuring that the Queue API is thread-safe in these scenarios.

In general, using an FGV is a way of capturing atomic operations on a single global object. When using them I would suggest questioning yourself as to whether any of the negatives above are deal-breakers.


Thanks tyk. That is a very clear explanation and you bring some great points I should consider regardless of whether this actually works, your second to last bullet point in particular is something I'm glad you brought to my attention. I guess I just didn't really understand or know that the reference would still be ok if the FGV went idle. I use fgvs all the time for storing data but I think I tried something with FGV+Queue in the past and it failed (obviously not for the reason of it being an FGV holding a queue) but I was under enough time pressure that I didn't have the chance to investigate further and must have filed it away in the old cranium as something cautionary.

0 Kudos
Message 5 of 6
(3,022 Views)

I put queues in Action Engines all the time.  Since queues are usually for messaging, I also tend to put my AE inside of a library and set it to be private.  I then have public VIs in the library that will use the AE to send the messages.

 

NOTE: Do NOT put the Dequeue inside of the AE.  You will regret it very quickly.  If the AE is in the Dequeue state, then all of the other threads will be blocked trying to use the AE and you will be stuck in deadlock.  Have only the loop that is processing the messages/data initialize the AE and it alone can dequeue the data.


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 6 of 6
(2,979 Views)