LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Forgive me for I have sinned...


@Ben wrote:

One of the things I teach me peers is to spend some time thinking about the shape of an application.

 

What are the independent components?

When and where do the components interact?

What is the nature of the interactions?

And one of the most important question for a language based on the Data Flow Paradigm "where is the data and how does it move?"

 


It's more or less my job to help people figure out why their application isn't running as expected and these questions, particularly the last one, do a good job of highlighting the ways I have seen people misuse globals. If you can answer all of the above questions for your application, even when you are using global variables, we can probably work through problems without too many headaches (usually).

 

I see problems come up when using global variables when you can't answer the question "where is the data and how does it move?". Usually functions will do exactly what you tell them to do so you'll be debugging some code getting closer and closer to finding the error until you find your problem VI. You probe all of the inputs and find out that the function is doing exactly what you are telling it to do, you just don't know why it would use those inputs at that stage in the application. This is when you get some more coffee because, if the programmer before you misused globals, it can be extremely difficult to figure out where the data is coming from. It wasn't hard to figure out what was going wrong, but it can be a nightmare to figure out why it's happening, and by extension fixing the issue.

 

I don't think that this issue is unique to using global variables, but I do think it is much easier to abuse globals and get yourself into this situation. I caution against using globals too liberally because it can make fixing bugs or extending functionality difficult.

Matt J | National Instruments | CLA
Message 21 of 28
(2,312 Views)

Nothing simpler than a Boolean global variable to interrupt a CPU intensive loop in a deep subVI (using a conditional terminal) from the UI.

Or is there?

Message 22 of 28
(2,270 Views)

@Joannick wrote:

Why are Globals so evil if overused ?


The evil is in the "overuse", not the global. Overuse implies a use case that would work equally well, or even better with less. Overuse is always evil!

 

Of course you could get from point A to point B in a 1970'ies Buick, but at 6 mpg and no catalytic converter, the load on your wallet and on the air you breathe is arguably larger than with a reasonably modern car. I remember the stage 3 smog alerts from 30 years ago in Los Angeles and they were awful. They are now completely gone thanks to clean air regulations (see for example).

 

I almost never use globals because they require an additional file, complicating the hierarchy. An action engine is of course also consists of an additional file, but it can have added internal smarts, which I often need. (e.g. some global states need to change based on values of other global states) 😄

 

All that said, I am very proud to have a stacked sequence as a central element in one of my top programs. In this case, any other structure, even a flat sequence, would not fit that particular use case very well. There are always exceptions!

 

 

0 Kudos
Message 23 of 28
(2,253 Views)

@altenbach wrote:

@Joannick wrote:

Why are Globals so evil if overused ?


The evil is in the "overuse", not the global. Overuse implies a use case that would work equally well, or even better with less. Overuse is always evil!

 

Of course you could get from point A to point B in a 1970'ies Buick, but at 6 mpg and no catalytic converter, the load on your wallet and on the air you breathe is arguably larger than with a reasonably modern car. I remember the stage 3 smog alerts from 30 years ago in Los Angeles and they were awful. They are now completely gone thanks to clean air regulations (see for example).

 

I almost never use globals because they require an additional file, complicating the hierarchy. An action engine is of course also consists of an additional file, but it can have added internal smarts, which I often need. (e.g. some global states need to change based on values of other global states) 😄

 

All that said, I am very proud to have a stacked sequence as a central element in one of my top programs. In this case, any other structure, even a flat sequence, would not fit that particular use case very well. There are always exceptions!

 

 


I need internal smarts!  I wonder if a functional global would work for me?

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 24 of 28
(2,236 Views)

@billko wrote:

I need internal smarts!  I wonder if a functional global would work for me?


No, but an Action Engine will.

Spoiler
For those who don't know, there are some of us in the LabVIEW community who define a Functional Global as a Get/Set Action Engine.  These are truly evil since they behave exactly the same as a Global Variable but with more overhead.

GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 25 of 28
(2,228 Views)

@crossrulz wrote:


No, but an Action Engine will.
Spoiler
For those who don't know, there are some of us in the LabVIEW community who define a Functional Global as a Get/Set Action Engine.  These are truly evil since they behave exactly the same as a Global Variable but with more overhead.

I haven't really thought about it in a long time, but I seem to recall that there is a slight but significant difference between functional globals and globals is that (non-reentrant)FuncGlobs have a bit of a mutex condition to them which protects against some types of race conditions.  A read / write to a FuncGlob will not happen while another read / write to the FuncGlob is in progress due to normal vi locking, where as there is no such safety with a normal global, where a thread can overwrite the data while a read is occurring and vice-versa.

As I said, its been a long time since I considered the matter.

Jon D
Certified LabVIEW Developer.
Message 26 of 28
(2,205 Views)

@Mythilt wrote:

@crossrulz wrote:


No, but an Action Engine will.
Spoiler
For those who don't know, there are some of us in the LabVIEW community who define a Functional Global as a Get/Set Action Engine.  These are truly evil since they behave exactly the same as a Global Variable but with more overhead.

I haven't really thought about it in a long time, but I seem to recall that there is a slight but significant difference between functional globals and globals is that (non-reentrant)FuncGlobs have a bit of a mutex condition to them which protects against some types of race conditions.  A read / write to a FuncGlob will not happen while another read / write to the FuncGlob is in progress due to normal vi locking, where as there is no such safety with a normal global, where a thread can overwrite the data while a read is occurring and vice-versa.

As I said, its been a long time since I considered the matter.


Jon,

 

A Functional global sharing a cluster and needing a single element of same to change would require a read to get the cluster, modify same outside the functional global and a write back to the global.

 

As long as the data (the cluster) is outside the FGV, the danger of race condition exists.

 

With AN Action Engine that has a method to "replace the cluster element INSIDE the AE" the mutex protect the encapsulated data.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 27 of 28
(2,193 Views)

I decided to do a quick check on why I recalled what I did, and a quick websearch brought up the following article, which points out what I was originally recalling (The LabVIEW Core 1 documentation/course) and as my hazy memory indicated, it was supposed to be protection by the non-reentrant nature of the subVI call.  (I never believed that FG's would block all race conditions, just ones caused by simultaneous access to the same dataspace in separate threads.)

Note also, my memory was faulty, since as you pointed out, just having the read/write wasn't enough.

 

http://labviewjournal.com/2011/08/race-conditions-and-functional-global-variables-in-labview/

Jon D
Certified LabVIEW Developer.
Message 28 of 28
(2,179 Views)