LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Preventing an action engine from being called by other threads for a short period of time

So, I coded myself in to a corner because I didn't think things all the way through... and I'm looking for ideas to escape that doesn't involve a big rewrite 🙂

 

I have an action engine that acts as a library. Other threads access that library to control hardware. I then wrote a VI that will read a CSV file and completely change out the library to new entries / values that can be done on the fly.  The design of this was so that I could have a single name (or in this case a whole bunch of single names) be mapped to different hardware IO channels depending on what was needed for the test.

 

My problem:  This VI that loads the library file works something like this:

  1. Load file in to memory.
  2. Call AE, command "Clear"
  3. Parse library data in to proper format (IO channel, type, warning limits, etc) and build new library array
  4. For each element in array
    1. Call AE, command "Add channel"
    2. Call AE, command "Update properties"

 

The problem just occorred to me (and should have much earlier Smiley Mad) that during the time between the "Clear" command and the completion of the parsing / for loop if any other section of code requests a value it will return an error.  This obviously is problematic. I strongly suspect that I'm going to need to just rework the AE and add a single command "Load Library", but that will be a pain.   The simplest solution I have been able to come up with:

 

  1. Make the AE run on a queue. When called the "Command" and "Data" variant gets enqueued. AE stops executing when queue is clear
  2. Add my "Load library file" directly in to the AE as a new command. Each AE call can then just become an enqueued element.

The biggest problem I have with this is the added overhead of the queue.  Since this is in line with the loop doing the control, I'm being stingy and don't want to give up those few extra microseconds that would be associated with every call.

 

 

So, after that long rambling intro... my question:  Can anyone think of a simple way to either "reserve" the AE to a single thread during this loading, or to update it without adding extra overhead?

 

0 Kudos
Message 1 of 7
(3,074 Views)

Is there any way that you could have a new command "Clear and Load" that just does both steps in a single call to the FGV?

Matt J | National Instruments | CLA
0 Kudos
Message 2 of 7
(3,051 Views)

Sure I could... but I'm lazy and don't want to because I figure it will be a couple hours to do Smiley Tongue 

 

I think I'm going to have ot though. I haven't come up with a better solution that I like.

0 Kudos
Message 3 of 7
(3,046 Views)

The answer is exactly what you think it is I'm afraid. Make your code deterministic and avoid the need to worry about what thread in what execution system could execute your action engine (or potentially many different threads in teh same action engine!)

0 Kudos
Message 4 of 7
(3,032 Views)

An Action Engine has typically two characteristics:

 

1) It uses uninitialized shift registers

2) In order to do that it is contained in a (while) loop

 

Now typically the loop termination terminal is wired so that it will always only execute once but that is not a requirement. You are free to wire this to a boolean inside some of the cases of the AE, and to also wire the AE method through an additional shift register. Now you have combined the Action Engine pattern with the State Machine pattern, something you should be careful about as it can make things clearly more complicated. But it also can be a very powerful pattern if you watch out to not overarchitect it into a super monster.

 

But your specific case would rather prompt me to do the entire initialisation inside the AE. So  instead of creating a VI that loads the configuration and calls the AE muultiple times you would write a VI that loads the configuratin and sorts it as you wish and place this inside the AE "Load" method. I'm not sure why you would want to add a queue here for this.

Rolf Kalbermatter
My Blog
Message 5 of 7
(3,022 Views)

I agree with Rolf. 

 

One of the concepts driving an action engine is that all the required actions take place in one call. So, to replace multiple data items without the possibility of othert callers getting partial updates, all the replacements need to take place in one call.

 

It seems to me that you have two options. Read the file, parse the data, and update the shift registers within the AE (probably requiring a new command). Or read and parse the file externally. Then call the AE while passing all the data items (in an array or array of clusters, perhaps) for updates within one call (again, probably requiring a new command).

 

If the command is an enum, make it a typedef and be sure that every copy of the constants in the code is replaced with the typedef constant. Then add the new command to the typedef.  No other changes will be required to the calling code anywhere except for the update from file section, which needs to be changed anyway. Similarly, if the command is a string, none of the existing string calls will need to be changed.

 

The time it takes to think it through, to write down the revised design for the AE, and the code modifications will likely be less than the time it takes to explain to your boss or your customer why the errors occurring in the original code happened.

 

Lynn

Message 6 of 7
(2,992 Views)

Thank you all for the feedback.  I ended up just biting the bullet and adding the new command to do the processing.  The whole reason I got myself into this mess was that I realized later I needed way more information stored with each variable and hadn't written a single command to do it.  I had however written a combination of commands that could do it easily and so I just did the combination externally without really thinking about it too much.  Not a mistake I'll make again 🙂

 

As for making my enum typedef... I learned that lesson the hard way once.  I'm likely a bit too anal about type defining things now.  "Hmm... I know this is only a cluster with a path and a Boolean and I have no reason to ever change it, but typedef it is!"

0 Kudos
Message 7 of 7
(2,971 Views)