What is a Functional Global Variable?

Updated Apr 22, 2022

Reported In

Software

  • LabVIEW
  • LabVIEW NXG

Issue Details

  • What is a Functional Global Variable?
  • I've been recommended to use an FGV in my code, but I'm not sure how to use one. How does an FGV work?

Solution

A Functional Global Variable (FGV) is a frequently used design pattern. An FGV is a non-reentrant VI featuring a while loop that iterates once, and has an un-initialized shift register. The purpose of this construction is to retain data between consecutive calls to the FGV.

FGVs can be used instead of global variables, mainly for two reasons:
  • Additional tasks can be performed when changing the stored value(s). Therefore, FGVs are sometimes also referred to as Action Engines (AE).
  • If used in an unsafe, accidental manner, normal global variables can lead to race conditions in your code. FGVs can help to prevent those.
Below is an example of a common use-case for FGVs. This FGV can be used as a timer SubVI. The Shift Registers are uninitialized outside of the While Loop, which results in the last stored value being passed around for each loop iteration. In this scenario, values are only initialized inside the "Initialize" Case.

FGV Example.png
Note: This image is a LabVIEW snippet, which includes LabVIEW code that you can reuse in your project. To use a snippet, right-click the image, save it to your computer, and drag the file onto your LabVIEW diagram.

Find a description on how to implement an FGV in the Functional Global Variables paragraph of Suggestions for Using Execution Systems and Priorities - LabVIEW 2018 Help.
A more detailed description of FGV's is available here: Functional global variable (FGV) - RIO Developer Essentials Guide for Academia.

Additional Information

Race conditions can occur when two pieces of parallel code modify the same variable. For example, two sections of code write a variable's value at the same time. The section of code that saves the variable's new value last overwrites the other code's written value. This can result in unexpected values when reading the variable later down the line.

Functional Global Variables can be used to prevent such actions that modify data. Please note that all critical sections of code must be protected by a non-reentrant FGV as a whole; this ensures that only one action executes at a time, so conflicting operations can never perform in parallel. Refer to Reentrancy: Allowing Simultaneous Calls to the Same SubVI for further information.

As a bad example, the following two parallel operations provoke a race condition, as the critical read-modify-write operations are implemented outside of the FGV:


In contract, in the following good example the critical read-modify-write sections of code have been implemented as actions of the FGV. As the FGV's non-reentrancy setting ensure only one action executes at a time, the two calls will always execute after each other, preventing a race condition.