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 (below) 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 Functional Global (or GFG)?
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.