LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
X.

Generalized Functional Global (GFG)

Status: Declined

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

All right, due some technicalities of the LabVIEW Idea Exchange forum, I am reposting this idea with the attachment I was planning to add in part 2 attached to the first part (why is it possible to insert images in a comment but not an attachment is beyond my understanding). There will still be 3 parts to it (assuming each of them fits in the maximum allocated size per post), plus an appendix.

 

This post is intended to present a solution to a problem that I was struggling with using LV2 global variables in my applications.

I don't claim that this is a unique or elegant solution or even the first of its kind, but I'd be curious to hear comments and suggestions about it.

Since it might be a long post, I will split it into 3 parts. Part 1 will discuss the intended functionalities. Part 2 will present my current implementation. Finally, I will try to summarize all this into Part 3, opening the discussion.

So you may want to wait until that part is published before posting your comments (if any).

 

Part 1: What do I mean by Generalized (LV2) Global Variable?

 

The LV2 global variable (or functional global, FG in short) is a well known structure (see for instance the beginning of this thread). It is a subVI which can store data locally in between calls. Usually it comes with a "Write" (or "Set") action and a "Read" (or "Get") action and a few inputs (and the same number of outputs). The inputs are the variables you want to update and the outputs, their corresponding values. The advantage of this design over the standard LV global is that there is only one copy of your variables in memory. If you are only using scalars or string, etc., using LV globals might not necessarily be a big problem, but if you start storing arrays of large data structure, it could result in a significant performance penalty. Note that there are other ways to pass data from VIs to VIs (queues and notifiers). Here, I am concerned with long term storage available from many parts of an architecture (e.g. subVIs or dynamically launched Vis).

To begin with, there are two major limitations with any design based on FG (at least that I am not happy with):

1) First, as emphasized above, due to the limited connectivity of a VI's connector pane, a FG cannot store a large number of variables. You can use clusters, but that is not always very practical.

2) Second, if you try to cramp as many variables in a single FG, you will probably run into the issue that you don't necessarily want to reset all variables at once, but maybe just one or two. That calls for a more sophisticated set of actions (Write Variable 1, Write Variable 2, etc, and possibly Write All, Clear All, etc).

In practice, if you use a lot of those FG, you will encounter a third problem:

3) In which FG did I store this @$%&! variable?

Some of my applications contain many of these FGs and I figured that this had become impractical to handle when I started duplicating them, having forgotten that I was handling variable "X" in an existing FG.

The obvious solution (apart from NOT using FGs) is to have a single FG that is designed such as to handle an unlimited number of variables of ANY type that can be modified at ANY TIME from ANYWHERE.

 I first looked at the WORM (Write Once Read Many) design of tbob (you’ve got to go to the end of the thread to download the final version of the WORM VI). It is a very clever and compact solution to store different types of variables within a single variant.

Two of the limitations I saw in this design are that you need to know:

1) the NAME of the variable you want to access.

2) the TYPE of the variable that you are WRITING or READING.

Let me clarify those two points.

It seems obvious that you HAVE TO know the name of the variable you are interested in. Well, that’s maybe true when you are designing your application. But after a month or more doing other things, it is not obvious anymore whether you’ve stored the number of components as “# Components” or “Component #” in that other part of the program that…where did I save it, BTW? You get my point…

The second point is apparently taken care of by tbob’s solution of outputting the variable (as a variant) as well as its type. The problem is that this “type” provides a very limited description. For instance, what do you do with a “cluster” type?

Finally, since I want to be able to modify any variable at any time, the “Write Once” feature is not cutting it for me. This is could be easily modified, but considering the previous comments, I decided to change the architecture some more. I will describe my solution in the next part.

 

21 Comments
tst
Knight of NI Knight of NI
Knight of NI

A few points:

 

1. The broken wire thing should not be happening (at least not in recent versions). If the user event refnum contains a typedef, it should update when you update the typedef and it should be linked to the typedef when you create the indicator. You seem to have 2010, so I don't know why this isn't happening in your case, but you should be able to examine and force it by right-clicking the refnum indicator and selecting Show Control. This will show you the data type and allow you to drag in a new data type.

 

2. As we discussed in the other thread, this doesn't create less copies than a global (in fact, I wouldn't be surprised if it creates more because of the detour through the variant array).

 

3. It doesn't handle the race-condition issue, which I see as the biggest problem with globals.

 

4. It takes a lot more work than globals and is not as flexible (e.g. creating another global VI is much easier).

 

5. It seems to me that the only advantage this has over globals is that you can add global functionality, such as logging who wrote the value, or throwing a user event, which is not something that would cause me to use this over globals.

 

6. As you mentioned, there are other encapsulation and communication tools, which I would much prefer to use if I'm not using globals.

 

 

Re. AQ's mention of making FGVs easier, someone might have some ideas, but I can't really think of anything at the moment, due to the customized nature of such code. I generally use FGVs if I have a place where I want a single instance in the code to have different states over time and I want it to hide it from the caller or in places where I want multiple instances which share a relatively simple internal state. Often, I would use a class where others might use an AE. You can have a look at this discussion for more on this. Near the end it also discusses OOP - http://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801#M240328


___________________
Try to take over the world!
X.
Trusted Enthusiast
Trusted Enthusiast

tst,

regarding your point 1, I tried to do what you said, but the control shown seems to be of the correct type (it is correctly linked to the typedef I have defined). Replacing that control by the actual typedef (sounds redundant, but I had to try) does not fix the problem. Any idea?

Regarding the other points:

2. I should have updated the "copies" comment. You indeed create a copy of the variable each time you access it anywhere in the software, but it is "on demand" only, not systematically, as with native global variables.

3. Since you have  two ways of accessing the variables:

- by a direct call to "Global Core.vi" or one of the Polymorphic instances of "Global Variable.vi". This does not tell you when the variable has been updated and by whom.

- monitoring the variables via the "Global Dynamic Event"

the latter in principle will allow you to handle race conditions.

4. It does take more work, but I think it is worth the investment if you are building a large application, considering the added convenience and long term flexibility. Again there might be much more elegant solutions, and I am hoping to learn about them.

tst
Knight of NI Knight of NI
Knight of NI

Re. the refnum, it seems to work fine in 2009. If it's not working for you, I suggest you create a simple example which illustrates just that problem and start a thread in the LV board.

 

> You indeed create a copy of the variable each time you access it anywhere in the software, but it is "on demand" only, not systematically, as with native global variables

 

 

I am fairly sure that globals also only create copies when they are accessed, but I have to admit to not having checked this closely. Since I never use globals for large data structures, this doesn't bother me,

 

I'm not sure why you think that the event works around the race condition issue. The only way to guarantee working around it is to create some sort of synchronization for read-write sequences. In AEs this is done because the AE itself serves as a mutex. For something like this, you would need to lock the resource to make sure that no one reads it before you write back to it or users will still have the old value.

 

I would suggest you start with the large app group for some info on communication and syncing mechanisms - http://decibel.ni.com/content/groups/large-labview-application-development


___________________
Try to take over the world!
X.
Trusted Enthusiast
Trusted Enthusiast

tst,

Thanks for the link and the suggestion to submit the "reference update problem" as a separate thread.

Let me withdraw my comment on race condition. This design is mainly intended to store race-condition-proof status information.

X.
Trusted Enthusiast
Trusted Enthusiast

Odd. I was preparing a stripped-dowb version of the VIs exhibiting the "reference update problem" discussed above and gradually adding stuff back. I eventually rebuilt the same exact "My Software Global Core.vi" and that problem is gone... The old VI, which, for what I can tell has exactly the same structure, still breaks each time I change the Typedef Enum. Not sure whether this is worth reporting to NI and how.

Sorry for having added this lenghty and useless Appendix. And very annoyed not to be able to:

- edit my preivous posts

- attach a revised version of the project

Oh well...

tst
Knight of NI Knight of NI
Knight of NI

I would suggest that you submit the old VI to NI, just in case it really is broken when it shouldn't be. Then, they can probably find out why and fix the bug. There's a support link at the top of the page which you should be able to use to do this.


___________________
Try to take over the world!
AristosQueue (NI)
NI Employee (retired)

> Sorry for having added this lenghty and useless Appendix. And very annoyed not to be able to:

>- edit my preivous posts

 

You can click on Options and select "Report to Moderator" and ask them to ammend your post. We do not allow people generally to edit older posts because the conversation can get really confused when there are replies to post that no longer exist. The moderators can add specific notes about edits, etc, while taking care that anyone who reads the thread later is aware that there was a later edit, so that any replies are still understood in their original context (or the moderator may amend those as well). It is especially problematic in the Idea Exchange where people may have kudos'd an idea when it read one thing and then it could get changed to something completely different that they might not actually favor.

X.
Trusted Enthusiast
Trusted Enthusiast

Aristos Queue,

the edit could be limited to ADDITIONS. People would learn to add footnote indicators (*,1,2,, etc) and expand them at the end of the post, for instance. Not being able to post attachments is also a major drag.

I also must smile at the concern about kudos. Do they have a monetary value? Are we talking about the risk of a kudo-bubble leading to a kudo-market crash? 😉

This being said, kudos to the forums and NI engineers participation and best wishes for 2011.

AristosQueue (NI)
NI Employee (retired)

> I also must smile at the concern about kudos. Do they have a monetary value?

> Are we talking about the risk of a kudo-bubble leading to a kudo-market crash? 😉

 

Although the Idea Exchange is not the only tool NI uses to decide which feature to work on next, we do want to be able to use the kudos to judge customer interest in a feature and as one of the inputs in to our allocation of development resources. For us to do that, the kudos must reflect user intent. If a user voted for a feature and then when NI evaluated the feature later, it was something completely different, we wouldn't know what the kudos actually meant.

X.
Trusted Enthusiast
Trusted Enthusiast

The Generalized Functional Global project has been modified (now GFG Release 2) to reflect the correction discussed above. Don't look for the Appendix where I was describing the work around to the corresponding (now irrelevant) issue, as it has been edited out upon my request.

The functionalities remain identical.