LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to used a queue within a global variable?

Is it possible to insert images acquired in a queue that would be read from a global variable by multiple threads?
0 Kudos
Message 1 of 3
(3,953 Views)
First, IMAQ already does something like this.

The real question that you have to answer before this question can be understood is: what type of image are you talking about? If this is an IMAQ type image, you already have the mechanism in place. If not, then you can do whatever you wish with the image.

My suggestion would be to store either the image, or in the case of IMAQ, the 'pointer' to the image, in a 'pseudo gloabal' VI. An example of this can be found in the Discussion Thread on Designs in LabVIEW. The example there is actually a combination of designs, but the essences of this VI is there. Basically, all you do is put the image in a shift register of a for loop that executes once. Whenever you call the VI, the image or other data are in th
e shift register.

I will try to post a specific example of this design. It will of course not be an image, but you will be able to get the idea.
0 Kudos
Message 2 of 3
(3,953 Views)
enneite:

I just finished doing this very thing with an IMAQ image.

The construct that you are grasping for to use is called a notifier.
Notifiers are polymorphic just like queues (i.e. they can accept any
data type in LabVIEW including an IMAQ image), and like a queue,
notifiers are automatically global by virtue of the fact that they are
named kernel objects.

In fact, not only are notifiers global within a particular LabVIEW
application, notifiers are system globals that can be shared between
different executable applications, even those not written in LabVIEW.

A queue is similar to a notifier in that it is also a named kernel
object and thus a system global but nevertheless a queue is the wrong
construct to use in this case though because of the way in which
queues work.

In a queue, the reader of the queue consumes the contents of the queue
by reading the queue. (There may be a way to "peek" at the queue
without removing an item from it now in LabVIEW, but I'm not familiar
with it.) A queue, like a stack, keeps all successive objects pushed
onto it up to a predefined number of items (by default infinite in
LabVIEW.)

The human analogy to the queue is a telephone call between two
parties. Everything that goes into the phone at one end comes out of
the phone at the other. It is designed to be a one to one connection.

In contrast to a queue, the reader of a notifier can not remove the
contents of the notifier by reading it. Only the writer of a notifier
can do that by writing a new value to the notifier. Notifiers are
only one object deep. When the new object gets put into a notifier by
the writer, the old object gets overwritten.

Because the reader of a notifier can not remove the contents of the
notifier by reading it, notifiers are the ideal way to "broadcast"
information to multiple clients who need to use it. Each reader can
read without removing the contents for the next reader.

The human analogy to the notifier is a radio station that broadcasts
to a listening audience. It is designed for the one to many
connection.

Notifiers are also automatically occurrences. They automatically
signal anyone waiting on a notifier that a new value is ready when the
writer writes a new value to the notifier.

Notifiers, like occurrences, allow clients who are waiting for
information to be instantaneously signalled when new information
becomes available without requiring any polling loop and without the
associated high CPU usage of a polling loop. Unlike polling,
notifiers and occurrences won't make you a victim of "race" conditions
and deadlocks (unless there is a bug in their implementation by NI.)

Because of no need to poll, 0% CPU wait states, instantaneous
signalling, and no race conditions or deadlocks, notifiers or
queues+occurrences are a much better more reliable way to pass data
between separate threads (dynamically launched VI's or between
parallel loops, etc.) in LabVIEW than using globals and polling loops.

(If you use a queue to send information between processes or threads
you will want to use it in conjunction with the set occurrence, wait
occurrence VI's to let you signal the client that new data is
available. Queues are not automatically occurrences like notifiers
are.)

Always use the acquire notifier or acquire queue vi to get a reference
to a notifier or a queue. DON'T stick the reference to a notifier or
a queue into a LabVIEW global to pass it around between VI's in
different threads. This won't work right. Instead use the
appropriate acquire reference VI in each place where you need to get a
reference to the notifier or queue object. If the object does not
exist, the operating system will create it and give you a reference,
if it does exist, the operating system will not create another one but
it will instead locate the existing object and give you a new
reference to it.

When you use notifiers or occurrences, be sure to allow for a
reasonable timeout period (250 milliseconds ought to work for most
applications) rather than using the infinite timeout that is the
default in LabVIEW. If you use an infinite timeout then you may need
to kill LabVIEW from the task manager rather than simply the labview
stop button if it gets "stuck" due to a coding error or other problem.

What you then do is check the timed out output of the notifier or
occurrence. If it timed out then you will probably do nothing, if it
did not you will be doing processing on the notifier data. (With
queues, if it times out, you can then check the number of items in the
queue, if it is >0 you may still want to do processing. Even if it
doesn't time out, you may want to check the # of items in queue to
decide whether or not to process.)

You may also need to make sure that if you hit the abort button or if
the code needs to stop programmatically that you send a notifier or
occurrence to all the listeners to let them exit without waiting to
time out.

You also need to make sure that for every acquire notifier, or acquire
queue that you do you also do a corresponding release notifier or
release queue when you are done.

Because notifiers and queues are named kernel objects they stick
around until you reboot your PC unless you kill them. They don't die
when the application that created them dies. This is by design
because they are intended for interprocess communications and there is
no way for the operating system to know when you are done with them if
you don't tell it because another application may still need them even
if it didn't create them.

If you write an application that uses notifiers or queues, you will
want to remove the stop from the labview VI menu and stop button from
the toolbar and place a stop button on your actual front panel and
wire it up so that you can programmatically control the shutdown of
the application so that all notifier and queue references are properly
disposed of.

If you don't do this then the operator can unceremoniously dump your
program without doing the proper cleanup of resources.

Once you have performed the corresponding individual release notifiers
or release queues you may also want to use the release all notifiers
or release all queues and destroy notifier or destroy queue to make
sure that all associated resources are released back to the operating
system. This may seem like killing a mouse with a cannon but it is
always good programming practice.

Douglas De Clue
LabVIEW programmer
ddeclue@bellsouth.net

P.S. For would be users of notifiers w/IMAQ: I recently submitted a
problem report with NI regarding using a notifier to send an IMAQ
image to dynamically launched VI's. I found that if the dynamically
launched VI was launched with the auto dispose references flag set
true, then something funky was happening to the IMAQ memory where it
wasn't being disposed of properly even though I disposed of all images
into the IMAQ "trashcan". My work around was to set the auto dispose
references flag false whereupon the memory gush (I won't call 2MB per
dynamic VI call just a leak) ended.





Labviewguru wrote in message news:<506500000005000000BB890000-1023576873000@exchange.ni.com>...
> First, IMAQ already does something like this.
>
> The real question that you have to answer before this question can be
> understood is: what type of image are you talking about? If this is
> an IMAQ type image, you already have the mechanism in place. If not,
> then you can do whatever you wish with the image.
>
> My suggestion would be to store either the image, or in the case of
> IMAQ, the 'pointer' to the image, in a 'pseudo gloabal' VI. An
> example of this can be found in the Discussion Thread on Designs in
> LabVIEW. The example there is actually a combination of designs, but
> the essences of this VI is there. Basically, all you do is put the
> image in a shift register of a for loop that executes once. Whenever
> you call the VI, the image or other data are in the shift register.
>
> I will try to post a specific example of this design. It will of
> course not be an image, but you will be able to get the idea.
0 Kudos
Message 3 of 3
(3,953 Views)