LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

occurrence refnum - access from a different vi.

Hi,

 

Labview help enticingly has this to say about Occurrence refnums:

 

"Occurrence Refnum—Used with the Occurrence functions. Use this type of refnum when you generate an occurrence in one VI but want to set or wait for the occurrence in another VI."

 

This is exactly what I want to do. I can create an occurrence refnum in vi #1 but I just cannot see how to 'get at' the refnum in vi #2 without using something like a global variable to pass it.

 

The vi's are all dynamically loaded so (unless I'm missing something else as well, very likely!) it is not possible to wire the occurrence or references.

 

I'm a 'C' programmer just starting out with Labview so please don't assume I know *anything* for sure.

0 Kudos
Message 1 of 10
(3,544 Views)

My advice to you comes straight from the LabVIEW help:

 

Note  National Instruments encourages you to use the Notifier Operations functions in place of occurrences for most operations.

0 Kudos
Message 2 of 10
(3,537 Views)

These two Nuggets may help you.

 

This Nugget focuses on Occurences and the discusion touches on re-entrancy in labVIEW.

 

This Nugget focuses on Action Engines which is a code construct that allows sharing data between threads and/or encapulating data and functionality (they act as a protected section).

 

have fun!

 

Ben

 

 

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

You can pass an occurence refnum to a subVI the way you would pass any other value, through the connector pane.

 

EDIT: Oops, I should have read the original post more carefully.  In that case, yes, you'll need a global variable or equivalent (such as a functional global variable).  Depending on how you're launching the VIs dynamically, you could also use "Set Control Value" to set the occurrence refnum value before running the VI.

0 Kudos
Message 4 of 10
(3,525 Views)

@nathand wrote:

You can pass an occurence refnum to a subVI the way you would pass any other value, through the connector pane.

 

EDIT: Oops, I should have read the original post more carefully.  In that case, yes, you'll need a global variable or equivalent (such as a functional global variable).


Agrred!

 

Functional Globals are the basis for Action Engines.

 

Ben

 


 

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

Thanks to everyone for the very useful responses. They have been very helpful and given me many ideas. My intention to use occurrences was to allow a vi to wait for an event, ie the occurrence, I now realise that waiting to dequeue some data from a named queue achieves the same effect. The vi, or part of it at least, will pend on an event generated by the Labview runtime. Another thing I now realise (please correct me if I have any of this wrong!) is that I can effectively achieve multithreading within a vi by using parallel loops. 

 

My situation is similar to the musical instrument 'multiple occurrence' nugget in that I have a main vi that acquires data then dispatches chunks of that data to a number of dynamically loaded worker vi's. These worker vi's all have front panels that the user can interact with asynchronously as well as having to process the incoming data from the main vi. Many of the controls and indicators in the worker vi's are affected by both user interaction via the GUI and the incoming data. There is also some feedback of data from the worker vi's to the main vi.

 

I am trying to adhere to a non-polled event driven model in order to maximise speed.

 

The structure I seem to be coming up is this:

 

The main vi acquires data, packages it up into clusters and places these clusters into named queues - one queue for each worker vi.

 

The worker vi block diagrams contain two parallel while loops. The first loop handles incoming data from the main vi and contains a sequence structure which works like this:

 

Seq:

1) Deque data cluster

2) Acquire semaphore

3) Update controls/indicators as required

4) Release semaphore

5) Back to 1)

 

The second loop handles user interaction. It contains an event structure handling events generated by control value changes. Each event case sub-diagram contains a sequence structure like this:

 

Seq:

1) Acquire semaphore

2) Update controls/indicators as required

3) Release semaphore

4) Back to 1)

 

For feedback of data from the worker vi's to the main vi I would use a further group of named queues. Data would be enqueued wherever appropriate in the worker vi's.

 

The main vi would use a similar scheme of parallel loops and semaphore to deal with dispatching acquired data to the worker vi's, handling its own front panel user interaction and receiving/processing data from the worker vi's.

 

The purpose of the semaphores is to serialise all reading/writing of the front panel controls and indicators.

 

Does this sound like a workable scheme?  

0 Kudos
Message 6 of 10
(3,495 Views)

I liked it right up until I got to the part about semaphores and controls being used as part of the data path.

 

In labVIEW we are best served by loking at the controls and indicators as I/O devices that let us update or get info from the user. They are not part of the data path. In LV, data lives in wires Shift Registers, queues or DVR (Data Value references).

 

WIth that in mind I encourage you to look again at that action Engine nugget to see the semaphores are built-in so if you modify your model such that you look tot an AE for the dat insead of the GUI, you would be well served.

 

Another approach would utilize multiple queues to move the data from it source (Producer) to all of the code that wants that data (Consumers). Search for Producer/Consumer for more info on that design pattern.

 

I hope that helps more than it hurts,

 

Ben 

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

I hope that helps more than it hurts,

 

Well, I guess you almost got half way through before you stopped liking it so it wasn't a total disaster!

 

I have re-read the AE nugget many times and now have a better understanding.

 

It seems as though the technique relies on Labview implementing the shift register as a static buffer and specifically *not* initialising this buffer to some value if nothing is wired to it. I understand why a new ('stack based', if you like) buffer would be allocated for a USR in a reentrant vi, but is it safe to rely on a specific implementation for a non-reentrant vi?

 

If the AE vi is used in two different vi's within the same application would this still work, ie will the same static buffer be used?

 

 

 

 

0 Kudos
Message 8 of 10
(3,461 Views)

@Spruce wrote:

I hope that helps more than it hurts,

 

Well, I guess you almost got half way through before you stopped liking it so it wasn't a total disaster!

 

I have re-read the AE nugget many times and now have a better understanding.

 

It seems as though the technique relies on Labview implementing the shift register as a static buffer and specifically *not* initialising this buffer to some value if nothing is wired to it. I understand why a new ('stack based', if you like) buffer would be allocated for a USR in a reentrant vi, but is it safe to rely on a specific implementation for a non-reentrant vi?

 

If the AE vi is used in two different vi's within the same application would this still work, ie will the same static buffer be used?

 

 

 

 


Yes!

 

And to extend the idea I have used AE's to share data not only between threads and between exe's, but also between machines across a network by exposting the AE and invoking the AE using VI Server call by reference in which case the call is mad on one PC and the inputs passed to the AE are transported across the network to the target where those inputs are used to call the AE on the target. The results of the AE method are then retuned to the VI server layer which in turn passes it back to the calling VI as if the AE was just a normal sub-VI.

 

The Un-initialized SR appears to be implmented as a "static local" (forgive my C jargon since it is very rusty) where the data space for the SR is not recreated on each cll but persist fromcall to call.

 

The real power of the AE comes into play when you promote it from what is often called a FGV (Functional Global Variable that functions like a global having a write and a read) to an AE by encapsulating the operations that act on a data structure (in the SRs) and returns the results to the same SR thereby preventing the possibility of a Race Condition. Race Conditions are part of any multithreding environement and since LV is by default multithreaded, we can't willy-nilly go off and ignore race Conditions.

 

In the case you outlined above you were using controls and indicators to share data and planned to use Semaphores to protect them. In theory that could work if you only used property nodes to read and right the objects. Using a local variable of the control would present an potential Race Conditions becuase of the way locals are implemented (Search for more on that topic) since they have a "special back door" that uses a buffer to apply the update without getting the UI thread involved.

 

And regarding the UI thread...

If you did implement your scheme using property node >>> value you would be forcing all of your data acces to operate in the UI thread (which is single threaded) incurring the over-head of thread swapping added to dealing with the bottle-neck of doing most of your work in a single thread. Running that code on an eight core machine would swamp one of the cores and leeve the other seven to twiddle their thumbs.

 

"No Sir, Don't like it." (Mr Horse from Ren and Stimpy ?)

 

Stepping back and doing the big picture thing for you...

 

LV is often looked at as just another programming langauage. This is true on the surface but "the devil is in the details." (Ross Perot). Since LV uses a data flow paradigm, development in LabVIEW is well served by ading an additional phase to the traditional design work which is very similar to the "Data normalization" applied to data bases ("The key the key and nothing but the key so help me Codd."). Altough I have no formal training in that area I am married to a DB-Guru so I have an informal awareness of the ideas.

 

the Dta analyisis work amounts to looking at the data structures I plan to use in an application and doing sanity checks and drawing up data paths to help me streamline my designs.

Some of the things I look at BEFORE CODING are;

 

1) Are the values I am grouping together used together? If not I seperate them.

 

2) What type of operations are perfomed on the data? The processing steps may benefit by me structuring the data as an array of clusters rather a flat cluster etc.

 

3) How big is the data set? Large data sets get special attention because they can sneak up and bite you. Benchmarking may be involved in this step so I know about perfomance issue ahead of time.

 

4) How busy is the data path? Busy data paths (DAQ to logging in high speed apps) is of particular concern. I have had to implement duplicate DAQ systems to provide a second data path for information coming from a RT machine or used SCRAMnet to provide the perfomance I need.

 

5) What all needs to touch the data? This combined wiht the above help to suggest where I am going to put the data. Do I put it in an AE so it can be shared and mashed from multiple locations, Do I put it in a queue to get the raw dat there fast...

 

I can probably go on a bit more but my point is it is only after the data anaylsis phase that I have a good idea what types of mechiansms will be used for each data structure.

 

Still trying to help,

 

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 10
(3,454 Views)

Ben wrote:

 

Yes!

 

And to extend the idea I have used AE's to share data not only between threads and between exe's, but also between machines across a network by exposting the AE and invoking the AE using VI Server call by reference in which case the call is mad on one PC and the inputs passed to the AE are transported across the network to the target where those inputs are used to call the AE on the target. The results of the AE method are then retuned to the VI server layer which in turn passes it back to the calling VI as if the AE was just a normal sub-VI.

 

The Un-initialized SR appears to be implmented as a "static local" (forgive my C jargon since it is very rusty) where the data space for the SR is not recreated on each cll but persist fromcall to call.

 

Ok, I've read a lot more now and I see that the USR technique seems to be officially sanctioned by NI. I was worried this might be exploiting undocumented behaviour which could change between compiler revisions. "Static local" is fine by me!

 

The real power of the AE comes into play when you promote it from what is often called a FGV (Functional Global Variable that functions like a global having a write and a read) to an AE by encapsulating the operations that act on a data structure (in the SRs) and returns the results to the same SR thereby preventing the possibility of a Race Condition. Race Conditions are part of any multithreding environement and since LV is by default multithreaded, we can't willy-nilly go off and ignore race Conditions.

 

It boils down to the same effect as wrapping every bit of code that accesses the data in some form of lock, whether that be a mutex, semaphore or whatever, but the encapsulation of the functionality with the data is quite elegant. I wasn't planning to ignore race conditions.

 

In the case you outlined above you were using controls and indicators to share data and planned to use Semaphores to protect them. In theory that could work if you only used property nodes to read and right the objects. Using a local variable of the control would present an potential Race Conditions becuase of the way locals are implemented (Search for more on that topic) since they have a "special back door" that uses a buffer to apply the update without getting the UI thread involved.

 

I have tended to do all reads and writes using property nodes because it isn't possible to wire data into a control. Plus, I read all sorts of warnings about local variables being inefficient and consuming lots of storage space. I didn't see any warnings about property nodes causing a performance hit in the help pages - in fact, I got the impression that the 'value(signal) property' would force the control to update but the 'value' property would not. Having re-read that section I now see that it is referring to the generation of UI events rather than updating the control. The two things just merged in my mind. I also see that Google has *lots* of info on the property node/UI thread switch problem.

 

I found a lot of material explaining the traditional multi-thread interleaved read-modify-write problem - I assume this is the cause of the race conditions you're referring to? 

 

And regarding the UI thread...

If you did implement your scheme using property node >>> value you would be forcing all of your data acces to operate in the UI thread (which is single threaded) incurring the over-head of thread swapping added to dealing with the bottle-neck of doing most of your work in a single thread. Running that code on an eight core machine would swamp one of the cores and leeve the other seven to twiddle their thumbs.

 

Yeah, that's bad news. Do you know whether the UI's of all top level windows in one .exe run in the same thread?

 

"No Sir, Don't like it." (Mr Horse from Ren and Stimpy ?)

 

Stepping back and doing the big picture thing for you...

 

LV is often looked at as just another programming langauage. This is true on the surface but "the devil is in the details." (Ross Perot). Since LV uses a data flow paradigm, development in LabVIEW is well served by ading an additional phase to the traditional design work which is very similar to the "Data normalization" applied to data bases ("The key the key and nothing but the key so help me Codd."). Altough I have no formal training in that area I am married to a DB-Guru so I have an informal awareness of the ideas.

 

I thought Labview was supposed to be 'programming made easy for electronic engineers'. It's funny, really, because I've only been timkering with it for a few weeks and I'm already up to my neck in multithreaded programming issues while just trying to put together a fairly trivial program with a few windows and a bit of data. I'm quite enjoying it, but I hadn't expected to be so concerned with what's going on under the hood quite so early. NI should do a course entitled "Advanced Labview for Complete Beginners".

 

the Dta analyisis work amounts to looking at the data structures I plan to use in an application and doing sanity checks and drawing up data paths to help me streamline my designs.

Some of the things I look at BEFORE CODING are;

 

1) Are the values I am grouping together used together? If not I seperate them.

 

2) What type of operations are perfomed on the data? The processing steps may benefit by me structuring the data as an array of clusters rather a flat cluster etc.

 

3) How big is the data set? Large data sets get special attention because they can sneak up and bite you. Benchmarking may be involved in this step so I know about perfomance issue ahead of time.

 

4) How busy is the data path? Busy data paths (DAQ to logging in high speed apps) is of particular concern. I have had to implement duplicate DAQ systems to provide a second data path for information coming from a RT machine or used SCRAMnet to provide the perfomance I need.

 

5) What all needs to touch the data? This combined wiht the above help to suggest where I am going to put the data. Do I put it in an AE so it can be shared and mashed from multiple locations, Do I put it in a queue to get the raw dat there fast...

 

I can probably go on a bit more but my point is it is only after the data anaylsis phase that I have a good idea what types of mechiansms will be used for each data structure.

 

That's all good advice and makes a lot of sense.

 

Still trying to help,

 

And I very much appreciate it!

 

Ben 


 

0 Kudos
Message 10 of 10
(3,446 Views)