LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Andromeda

Shared variables are deliberately crippled

Status: Declined

Any idea that has received less than 7 kudos within 7 years after posting will be automatically declined.

One of the nice features in the last few versions of LabVIEW is the Shared Variable. Unlike global variables, they can be programmatically created, which would appear to open up a range of new applications for LabVIEW.

 

Unfortunately, they cannot be assigned default values unless the customer purchases the onerously expensive DSC module. Making matters worse, there is a run-time license associated with distributed copies of an application which uses the DSC.

 

Naturally, this severely limits the usefulness of shared variables.

 

This is not the first time that we have seen NI take a key feature which a customer would expect to be part of the PDS, and put it into an optional module. I'm sure that this is intended to “encourage” customers to purchase optional modules.

 

Our corporate experience has been the opposite - we have seen one of our clients blacklist NI as a supplier, after they were burned by another instance of NI's callous feature bundling.

 

 

J. Heerema, PhD - LabVIEW specialist
23 Comments
viScience
Active Participant

re:slightly off topic idea - I am wondering if it maybe possible to create native NSV events.  It appears that in CVI you can register for a SV value change event callback.  I assume then, a dll could be built that would accept a NSV url and then generate a user event or possibly execute a LV vi in the callback.  Anybody interested in working on this?

 

In regards to how tag properties are stored...I have vi's that compile my config workbooks to GXML files which are then deployed to every target.  Upon startup each target reads and 'compiles' the GXML data into memory resident FGV's which are optimized to provide access to tag parameters by name and type.  Also, the compilation groups data types so that RT processes can efficiently read out type specific parameters as a single cluster of tag parameters or an array of parameters.  I have fast (10ms) RT processes which continuously read tag parameters and apply filtering, scaling, zero offset, etc.  I have other processes that use tag information to build HMI control description strings and could programmatically bind HMI controls to NSV's. This same mechanism holds NSV and IOV references that are used for programmatic transfer of all IOV's through a scaling process to CVT (Current Value Tables) and NSV's.  On a cRIO, I use this technique to process ~100 channels of data at an 40Hz rate.  Keeping my NSV datatypes simple allows me to directly bind to HMI controls, view in the DSM and automagically log every NSV channel to a citadel historical database.

Andromeda
Member

Thanks for the summary of your approach!

 

If you are still willing to share some of your simple tools, I would appreciate seeing them.

I also use FGVs to implement current/historical value tables, but hadn't thought of using them to organize the variable properties (which I think you call tag parameters). Putting property type information into FGVs would almost certainly be more efficient than using complex NSVs. Plus, as you say, there are advantages to using simple NSV data types, such as being able to bind NSVs to HMI controls. On the other hand, it means using one mechanism for properties, and another one for values. Hmmmm .... design decisions are always interesting! The voice of your experience is appreciated.

 

 

J. Heerema, PhD - LabVIEW specialist
MarkBlack
Active Participant

To be clear I am interpreting this feedback as "The Shared Variable initial value property should be included in core LabVIEW because its application is more general purpose than SCADA solutions using LabVIEW DSC."

 

When the Shared Variable was originally developed we intended for it to only be included in the LabVIEW DSC module, but as its obvious usefulness for LabVIEW and LabVIEW RT applications became apparent, a decision was made to include a subset of the features of the Shared Variable in core LabVIEW.  The full Shared Variable feature set was included in the DSC module.  We believe there are certain features included in the DSC module that could be argued are general purpose enough to be included in core LabVIEW.  If you believe this or another feature of the Shared Variable should be included in Core LabVIEW this is the place to voice and vote for these opinions.  

 

On a side note, its important to understand what the initial value setting for a Shared Variable actually does.  Shared Variables do not reinitialize to their initial value for each new run of a VI, but instead the initial value is set when the owning process is deployed, or the machine on which the process resides reboots.  This, by design, is more inline with the initial value behavior of tags in other supervisory control software.  This behavior can be worked-around in several ways depending on your needs, and the "correctness" of this behavior is certainly up to debate.  That said that discussion is probably best suited for our standard discussions forums rather than Idea Exchange.  

 

Thanks for the feedback.  We look forward to receiving more.

 

Mark 

LabVIEW R&D

DSC, Web, and Network Technology

Mark
NI App Software R&D
Andromeda
Member

Thanks for your comments.

 

Yes, your interpretation of the comment is corrrect, and I believe that the behaviour you describe for shared variable initialization is also the right way to initialize them.

J. Heerema, PhD - LabVIEW specialist
viScience
Active Participant

BLAQmx - SV events are a very general purpose mechanism that should be on the list of DSC features to be included in LV proper.  It is my understanding the CVI already includes this, is that correct?

Andromeda
Member

Looking at the shared variable implementation, it's fairly obvious that it was originally developed for the DSC module.

 

The problem with leaving shared variables in the DSC module, I think, was that LabVIEW's global variables were pretty much ignored for several years as a result. After all, who would put work into implementing much-needed improvements to global variables, when NI already had a promsing alternative to them?

 

Speaking of improvements, another one I'd like to see, would be allowing programatic access to single-process shared variables, instead of just network shared variables.

 

 

J. Heerema, PhD - LabVIEW specialist
AristosQueue (NI)
NI Employee (retired)

> After all, who would put work into implementing much-needed improvements

> to global variables, when NI already had a promsing alternative to them?

 

Shared variables are useful, but not as a replacement for globals.

 

In LV R&D, we don't see improving globals as something desirable. LabVIEW has other tools that we really hope you use instead of global variables for any real development. Globals are easy for quick prototypes, but once an application starts having significant design requirements for initialization, consistent state maintenance, etc, it should really be using other aspects of LabVIEW and abandoning globals entirely. The concept of a globally accessible variable state has issues that cannot be overcome by a more clever LabVIEW compiler or development environment. The shared variables came to LabVIEW not as an improvment for globals but to help communication with FPGA and RT, and to allow LV better control over DSC itself. You cite shared variables as a "promising alternative." The shared variables really aren't an alternative to globals... when you use them as a global, they have all the same issues as existing globals as far as data copies, program verification and possible race conditions. Stick to using them as a one-way communications tool and they work well.

Andromeda
Member

Thanks for your comments on globals.

I would agree that novice developers often use globals inappropriately. Having said that though, I see an ongoing need for persistent stative objects which have multiple consumers.

 One of the common design patterns for such objects is the so-called "LabVIEW-2 style global", which has been renamed as a "functional" GV. These objects have a variety of uses, and are very commonly used - often inappropriately, but also because they are a useful way to persist objects which may have multiple consumers.

 The problem with FGVs though, is that they confuse implementation with syntax. They rely on a particular implementation of shift registers, rather than on a feature of the language. Their relative freedom from race conditions is dependent on the assumption that each instance is implicitly locked because of being single threaded. The lifespan of an FSV is coupled to the lifespan of the VI which implements it, which means that developers have to pay attention to it.

From a language design point of view, it's important to decouple syntax from implementation. That way, the implementation can be optimized without breaking existing code. This is an area where LabVIEW needs appropriate syntax.

My own area of practice is in the development of applications which may contain thousands of VIs. One of the common design patterns for such applications is the producer / consumer model, where there can be multiple consumers, and often multiple producers as well.

It's typical to create information service objects which accept information requests, and make the results available to multiple consumers. One of the models for passing requests to the service objects. is the LabVIEW queue object.

In a simple implementation of producers, consumers, and service objects, you might have an application constructor which instantiates producers, consumers, and service objects. In a small application, the object constructors might be passed references to the queues which will be used. However, there is a limit to the number of arguments which can easily be passed to a constructor - typically no more than half a dozen.

In larger applications, I would argue that this is clumsy, and potentially impossible to implement, due to differing object lifespans. It may be more appropriate to put the queue references into a global variable. Service objects can test the reference to see if the queue exists, and attach to it it if it does.

This has both the disadvantage and the advantage of putting control of the reference lifespan in the developer's hands. It's possible to keep queues alive longer than necessary, by keeping global references to them alive. On the other hand, it might be the best way to let different parts of the application, which live in different execution threads, know whether the queue is available for use.

Going back to the multi-consumer part of the design pattern, the producer may not know who all of the consumers are. I would argue that knowing who all of the consumers are would violate design encapsulation, and be inappropriate. So the question arises as to how consumers can determine where to obtain the information which they happen to want.

The generalized form of one potential answer is stative objects. A database is a common stative object which may implement desirable behavior such as notifiers, modification time inspection, optimized access, etc. But the need for stative objects isn't limited to applications which use a database.

LabVIEW's shared variables are another example of stative objects, as are globals. Both of them have strengths and weaknesses.

It’s often desirable for consumers to be able to inspect a stative object to determine whether the information they need is available and current. If it is not, they might become a request producer, and ask for a newer version of the information. If it is reasonably current, they might just use what’s in the stative object (one way to do this is to inspect the time that the value was last updated, if the object supports a modification time property).

There can be valid arguments for funneling all information requests to a single service provider. Even if we take that approach, the service provider will still need to store the information somewhere, so we still need better stative objects.
 
So I come back to the argument that there is an ongoing need for stative information which can be consumed by multiple processes. Queues and occurrences can reduce the number of global stative objects in some, but not all cases. LabVIEW globals currently have serious deficiencies if used as such objects. FGVs have different, but equally serious deficiencies.  SVs share many of the deficiencies of globals, but at least they implement a variety of desirable behaviours which are not available for globals.  I have some thoughts on desirable improvements, but they might be best left for another time.

If you’re read this far, thanks for reading. If others see a need for better stative objects, we might have an interesting discussion…

J. Heerema, PhD - LabVIEW specialist
AristosQueue (NI)
NI Employee (retired)

> If you’re read this far, thanks for reading. If others see a need for

> better stative objects, we might have an interesting discussion…

 

a) I think Data Value References cover every aspect of stative storage that you mentioned and do it better than global VIs.

 

b) The disjunction of producer from consumer can be done through various forms of directed communication, not stative storage. I presented one way to do this here.

 

c) Communication among multiple processes is a very hot topic at the moment. It is in the running to be the topic at the Certified LabVIEW Architect Summit this year, happening in March. If you are a CLA (or can get your certification by that time), I'd encourage you to attend (assuming this topic does finally win as the topic for the summit).

Andromeda
Member

Thanks for your thoughts.

 

I've spent some time over the past few days looking at your Actor framework. There's a lot to like about it - I can see myself testing it out on a project, so thanks for pointing me toward it.

 

I'm not quite convinced that Data Value References cover everything that I'd like stative objects to do. They are pretty closely modeled on other languages, where you instantiate objects, and pass references to them as needed, so they feel familiar in that way. They don't seem quite complete within the LabVIEW visual framework though, although I'm still trying to articulate what it is that seems missing.

 

Maybe what I'm missing is the collection classes which have become popular in some other languages. Of course I could write my own, but there are details to consider, like making it possible for LV probes to dereference them and show the collection objects behind the references.

 

I see the tools for directed communication as being better developed than the tools for general publish/subscribe. Your Actor framework seems to be pretty good for directed communication, but as soon as you get into more general publish/subscribe, the subscription process seems to carry a bit of excess baggage. I'd like to see something that builds on the nice visual metaphor that you get from LV globals and SVs, where potential clients can ask a repository whether the object they want is available.

 

In the multi-threaded LabVIEW environment, you're always dealing with inter-process communication, whether it's lightwight threads, or full processes.  Every time a user asks to see something, you're probably spinning up at least one top level process, and possible a daemon or two as well. For lightweight inter-process communication, LV globals are attractive in a lot of ways, but they also have all of the well known problems of inefficiency and potential misuse. I'd like to see something that builds on the good things about globals, and provides first-class implementations of things like in-place modification, links to mutexes, scoped visiblity, and so on.

 

Thanks again for your thoughts. I'll be overseas in March, so the CLA summit isn't an option for me this year, but I'll be curious to see what comes out of it!

J. Heerema, PhD - LabVIEW specialist