LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Locking a global variable

I'm currently just starting to make use of a handful of global variables in a project I'm working on.  I'm aware that globals are typically good to avoid, but I think there is a fairly good reason to do so in this case, and so long as I write the code intelligently, I'm sure race conditions and the like can be avoided.
 
My questions is, what it is a good way to lock a global variable that needs to be accessible from multiple separate top-level VIs?  I am automating the process of logging into and configuring a peice of homegrown equipment, and TestStand is being used to initiate each of the steps....  (Log in, access super-user mode, set serial #, etc.)  The trouble is, multiple TestStand threads could be reading/writing at the same time.  (They will be reading/writing separate elements of an array, but nevertheless, the only way I would know to perform an update is to read the entire array, write the element in question, and write the array back to the global.  I'm sure this is terribly inefficient, but the alternative is to keep this information in TestStand - an option that the powers that be at my company don't want.
 
In any case, my initial reaction was to look into semaphores.  But it sounds like semaphores only persist until the VI that creates them dies...  In my case, there is no VI that persists throughout the entire process - they are individually called by TestStand.  Is there some standard way of implementing "global semaphores" for lack of a better term?  That way I could write a VI that:
1) Locks the semaphore
2) Reads the global
3) Updates an element of the global data
4) Writes the data back into the global
5) Unlocks the semaphore
 
Just making such a VI non-reentrant would probably work, except I think the VI needs to be reentrant...  I don't think TestStand will just wait for a non-reentrant VI to finish if it's currently in use - I think it throws an error.
 
Any direction on this would be greatly appreciated.
-Rob
0 Kudos
Message 1 of 5
(3,122 Views)
You might want to implement this as an action engine. For a primer, have a look at the Action Engine© architecture.
 
Basically, you would hold the array in an uninitialized shift register of a non-reentrant subVI. To replace or read a certain array element, all you need to tell it the desired operation and position. You almost never shuffle the entire array across, just the desired element. Since it only can be called from one location at a time, reads and writes cannot step on each others toes.
 
With the array in a global variable, each operation needs to do a "read..modify...write" and if multiple operations overlap, you'll get mistakes. AE protects against this.
Message 2 of 5
(3,108 Views)

Thanks for the feedback.  I will probably make use of the AE concept.  My only concern is whether the LabVIEW engine or TestStand engine will queue up requests to execute the non-reentrant VI from separate threads.  I assume this must be handled somehow - it wouldn't be particularly intelligent to rely on non-reentrance to lock a resource if it throws an error every time two code modules attempt to access it in parallel.  I tried to search for some info on how LabVIEW manages this, but maybe I was using the wrong keywords.  In general though, action engines seem to be the way to go - it's almost like forcing LabVIEW against its will to be object-oriented. 🙂

0 Kudos
Message 3 of 5
(3,088 Views)
Queuing up requests is not exactly the best way to think about this situation. LabVIEW is a dataflow language. The result is that if the AE is busy elsewhere, the other thread will wait at that point for the resource to become available. I don't know how it is implemented internally, but you could think of it as a free, hidden semaphore. LV's internal scheduler seems to do a very good job of deciding which node to execute next. If the AE is hanging on a wire with data on it, the AE will execute when its turn comes.

Lynn
Message 4 of 5
(3,066 Views)

One detail .... AE or other....

If the the AE is unloaded from memory in-between steps, care should be taken to ensure the default value are not used.

In that case, a config file (ini) can be used to store the values and a stategic use of "first Call" to ensure the AE (or whatever) has the proper values.

I am not a TestStand guy but I believe it is possible to launch a VI that runs in the background to keep the AE valid.

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 5 of 5
(3,057 Views)