LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

updating cluster elements using action engine

Hi, I'm looking for examples on using action engines to update element(s) of a cluster.

My FP has a tab control with indicators grouped in a cluster for each tab.

The indicators are updated from multiple sources and to avoid racing condition, I would like to use the action engine method.

However, I couldn't find examples on how to write/set multiple elements of a cluster using action engines.

Can a kind soul point me to the right direction?

 

Thanks in advance.

0 Kudos
Message 1 of 10
(3,068 Views)

I'm going to assume you are familiar with a simple get-set functional global. You would do as follows:

 

Let's say you have a big cluster with three smaller clusters inside it: cluster1, cluster 2, and cluster 3 inside that big cluster. But, you only want to set new values for cluster1 and cluster2, while keeping the current value for cluster 3. You do a "get" on your functional global, then you do bundle by name, bundle the two elements you want to set but do not bundle the third. Then do a set on the same functional global.

 

See image below. The "true" boolean is just telling the functional global to set, not get.:

 

 

0 Kudos
Message 2 of 10
(3,065 Views)

@for(imstuck) wrote:

 


This doesn't solve the problem at all, as you still have race conditions - if the cluster was read in two places at the same time, then the changes the earlier write makes will be overwritten when the second write occurs.

 

What I would suggest is ditching the AE. Create a DVR to the cluster and use the IPE structure to modify it (which protects against race conditions by automatically locking the data until you write back). If you want to simplify your life, just turn the cluster into a class (there's even a right click option for that) and you will get all the accessors VI for free (and accessible through property nodes). If you want further protection, you can have VIs in the class which will do all the operations you want, but that would require manual work for each one to call the DVR.

 

 

I would suggest going through Ben's nugget here, particularly from reply 57 and onwards - http://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801

The code in that reply is old-style GOOP, but the basic concepts still apply to LVOOP, except it's easier in LVOOP.


___________________
Try to take over the world!
Message 3 of 10
(3,049 Views)

Thanks Greg for your solution.

Initially I had thought of the same method when I was going through some articles on functional globals.

Yet, I have this doubt:

If I have two separate loops updating different elements of the same cluster, won't there be a risk for racing?
Say loop 1 gets cluster A, and before it sets the new element values, loops 2 gets cluster A.

Won't loop 2 be getting old data?

 

0 Kudos
Message 4 of 10
(3,043 Views)

@tst wrote:

@for(imstuck) wrote:


This doesn't solve the problem at all, as you still have race conditions - if the cluster was read in two places at the same time, then the changes the earlier write makes will be overwritten when the second write occurs.


I completely forgot to speak to that point when responding. I just thought the OP wanted to know how to update elements of a cluster without updating the whole thing.

 

Juli4n, you're absolutely right there could be an issue with a race condition (as TST explains also), and TSTs solution is something you should consider.

0 Kudos
Message 5 of 10
(3,042 Views)

Hi tst,

I will try and have a look at implementing the DVR and IPE to modify the clusters. As I'm fairly new LabVIEW, this will take some time though!

Thanks for your suggestions.

0 Kudos
Message 6 of 10
(3,037 Views)

In the meantime, there are simple workarounds you can use while keeping the "action engine" structure.  The essence of it is to package all the possible "set" functions *INSIDE* the AE with a distinct action for each cluster element that needs to be updated.

 

This has the result of making the read-modify-write sequence atomic because whenever 1 process calls the AE vi, any other processes trying to call it simultaneously will be blocked until the first one finishes.  (So make sure the code inside the AE can execute and finish quickly.)

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 7 of 10
(3,009 Views)

I would be more inclined to recommend using a LVOOP object rather than an AE. With an AE you get a single connector pane that must work for all of your various combiations of actions and inputs/outputs. With a LVOOP object you get specific methods that do exactly what you need and have a specific connector pane related to that method.

 

The other thing to consider since you are basically trying to keep the UI up to date is rather than use an AE is to use messaging to send updates to the UI. You can use queues/notifiers or user events to send the updates. This also helps to decouple your processing fro your UI.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 8 of 10
(3,002 Views)

functionalGloabalwithVariant.png

try this.

do not read from an FG and write back to an FG shiftregister. this will create race conditions. you should only make changes to the data inside the FG VI, for that a simple variant input can be used.

Kudos always welcome for helpful posts 🙂
0 Kudos
Message 9 of 10
(2,994 Views)

@RENN wrote:

functionalGloabalwithVariant.png

try this.

do not read from an FG and write back to an FG shiftregister. this will create race conditions. you should only make changes to the data inside the FG VI, for that a simple variant input can be used.


Using the variant like this is pointless. If the Read Value outputs the actual data type there is no good reason to input it as a variant. The input should be the same data type. While variants can be very useful in the example above it does more to obfuscate the code than solve any particular issue.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 10 of 10
(2,990 Views)