05-24-2019 09:35 AM
I am attempting to update a LabVIEW 6.0 program to LabVIEW 2015. The original programmer took advantage of the "remove from end" terminal of "Remove Queue Element.vi". The LV 2015 version does not have this terminal. But a text box on the vi's schematic reads, 'The "remove from end" terminal has been removed in LV 7.0. Please modify your code as necessary. See Knowledge Base at ni.com for details.'
Sadly, although the Knowledge Base autofilled my words while searching, it came up blank on the subject. Does anyone know what it used to say?
Thanks,
Tom
05-24-2019 10:42 AM - edited 05-24-2019 10:43 AM
To remove the last element in a queue perform the following:
05-24-2019 10:46 AM
Well at a guess it probably said something like "we removed this because it's missing the point of using a queue entirely". A queue is for any number of locations to write things to, which are then run in order by one and just one section of code. Taking things from the opposite end means you either should have used the "enqueue element at opposite end" function, or that your code is doing some sort of screening or modification of the queue elements, which you should solve by having multiple parallel queues or a different data structure entirely.
If you DO want to use this, the closest way is to use "Flush queue" to remove all the elements as an array, remove the last element, and then enqueue the rest all over again in the same order. You'll also have to be certain you don't have any other operations running in parallel that might insert another item in the queue while you're doing it, so you might need to add a Semaphore or other control mechanism like it to lock down the queue during the improvised "remove from end" that you've just added.
Personally I'd recommend trying to determine what led the original programmer to think this was a good idea, and either switch to a data structure that makes more sense for the use case or find a different way to deal with whatever the last element of the queue was needed for.
If you can't figure it out, you could just post the old code so we could see it.
05-25-2019 11:17 AM - edited 05-25-2019 11:18 AM
@Minions wrote:
To remove the last element in a queue perform the following:
- Determine size of current queue (N)
- Subtract 1 from queue size (N-1)
- Run a for loop for N-1 times that will Dequeue element then Enqueue element
- After the loop ends, the next element in the queue would have been the last element: simply use the Dequeue Element to remove that last Enqueued element.
Also. Be sure nothing else is enqueueing data while you are doing this otherwise those new elements will get mixed in with the older elements you are cycling through.
EDIT: I see Kyle, whose message I hadn't read yet gave a good write-up saying the same thing.
05-26-2019 07:26 AM
@Kyle97330 wrote:
You'll also have to be certain you don't have any other operations running in parallel that might insert another item in the queue while you're doing it, so you might need to add a Semaphore or other control mechanism like it to lock down the queue during the improvised "remove from end" that you've just added.
Manage the queue with an Action Engine. The VI boundary will act as your Semaphore, and be a lot more efficient. However, you still need to be VERY careful about handling a normal Dequeue, regardless of the route taken.
But from a general perspective, dequeuing from the opposite end sounds like it would be riddled with race conditions. I would really like to see what the code it trying to do.
05-26-2019 10:28 AM
It just occurred to me to ask the following question -- are you trying to implement a "Stack", a LIFO (Last in, First out) collection? I'd create an Action Engine (called "Stack") with an internal Array (held in a Shift Register) to hold the Stack Contents, and operations "Init", "Push", "Pop", and "Status", having the following functions:
Bob Schor
05-26-2019 01:06 PM
I'd venture that the "Remove from End" parameter was an early attempt to support optional stack-like behavior. Nowadays, stack-like behavior is supported by the primitive "Enqueue at Opposite End" which places the enqueued element directly at the front of the queue.
Exactly *why* the change was made I cannot say, but I can notice that it shifts *responsibility* for choosing stack-like behavior from the dequeue side over to the enqueue side. This does make sense to me - the enqueuer knows what it's adding, the dequeuer only finds out what it gets after doing the dequeue. So the enqueuer is in a better position to make the decision about inverting the normal priority.
Queues were given a major overhaul back around that time and have proven to be very well thought-out and highly performant. I'm inclined to recommend you carefully understand the program's *reasoning* for pulling things off the back of the queue and then, if justified, re-implement with the new method of enqueuing at the front.
Keep in mind that the "if justified" part is worth careful thought and attention. Occasionally inverting the priority can be useful if you're careful and judicious, but can lead to real problems if you aren't.
-Kevin P