action engine

16
Action Engines, What are They? “An action engine is Ben's term f or a functional global which includes extra actions other than just holding the data.”  (tst , 03-13-2007 01:18 PM) In a nut shell tst has nailed it except for the “Ben’s term” part. I was originally exposed to the term "Action Engine" by reading the book ""LabVIEW Applications Development A Course on Advanced LabVIEW Programming Techniques*”. But before I get into details of the Action Engine (AE), I will attempt to clarify some terminology. Functional Globals Functional Globals (FG) are VIs that are functionally equivalent to LabVIEW globals. Functional Globals store information. You can read them or write them and that is it. No fancy stuff. Functional Globals are also referred to as LV2 globals because LV2 did not have globals but it did support Un-initialized Shift Registers (USRs). The USR is the entity that stores the information. USR.jpg USR’s Shift Registers (SR) come in two varieties “Initialized” and “un -initialized”. The presence or absence of a wire feeding the SR from outside the loop distinguishes how LabVIEW will implement the SR. If there is NO wire feeding a shift register (A), then the SR is not initialized. This is called an “Un -Initialized Shift Register”. The USR variety is implemented as static buffer that is re-used from call to call. The values written to the USR in and earlier call persist for access (B) in latter calls**. A Functional Global exploits this behavior by implementing two methods of 

Upload: maitetxu25

Post on 05-Apr-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 1/16

Action Engines, What are They? 

“An action engine is Ben's term for a functional global which includes extra actions

other than just holding the data.” 

(tst , 03-13-2007 01:18 PM) 

In a nut shell tst has nailed it except for the “Ben’s term” part. I was originally exposed

to the term "Action Engine"

by reading the book ""LabVIEW Applications Development A Course on Advanced

LabVIEW Programming Techniques*”. But

before I get into details of the Action Engine (AE), I will attempt to clarify some

terminology.

Functional Globals 

Functional Globals (FG) are VIs that are functionally equivalent to LabVIEW globals.

Functional Globals storeinformation. You can read them or write them and that is it. No fancy stuff. Functional

Globals are also referred to as

LV2 globals because LV2 did not have globals but it did support Un-initialized Shift

Registers (USRs). The USR is the

entity that stores the information.

USR.jpg

USR’s 

Shift Registers (SR) come in two varieties “Initialized” and “un-initialized”. The

presence or absence of a wire

feeding the SR from outside the loop distinguishes how LabVIEW will implement the

SR. If there is NO wire feeding a

shift register (A), then the SR is not initialized. This is called an “Un-Initialized Shift

Register”. The USR variety 

is implemented as static buffer that is re-used from call to call. The values written tothe USR in and earlier call

persist for access (B) in latter calls**. A Functional Global exploits this behavior by

implementing two methods of 

Page 2: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 2/16

interacting with the contents of the USR.

Functional Global.JPG

In the “Write” action (not shown) the value of “Numeric in” is placed in the USR. In the

“Read” action the contents of  

the USR are returned via Numeric out.

Action Engines 

An Action Engine (AE) can be thought of as a machine (Engine) that performs some

useful task (action) often on

something (typically but not limited to data in a USR). Functional Globals are very

specific type of Action Engine.

They have two actions “Write” and “Read”. They operate on the data stored in the USR

either by replacing or using the

contents of the USR. So AE’s are a superset of Functional Globals. In many documents

the terms AE and FG are

interchangeable. A recent poll on LAVA has indicated that Functional Global is the

most popular term. Since this Nugget

was prompted by answering the question “what is an AE?” in the remainder of this

document you will find that I will

generally use the term AE.

Do What to What?

AE design revolves around the ways the shared resource must be accessed

manipulated or monitored. In a Functional

Global, the actions “Write” and “Read” are appropriate. That is not necessarily the

case for AEs. AEs can have entirely

different set of actions depending on the interaction requirements for the information

stored in the USR. A short list

follows.

Page 3: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 3/16

A Configuration AE could allow for multiple processes to share a single copy of the

system configuration (in a USR) by

providing actions like “Set Device ID”, Set Device ON-Line… 

A hardware device can be realized as an AE that presents actions appropriate to the

physical phenomenon being measured

or controlled.

A DO Port Controller AE could store a reference to the physical device in one SR and

the port status in another SR and

have action like: Set Main Motor On”, “E-Stop”, … 

An Instrument can be implemented to store the device name and settings with actions

like “Set Input ON” “Auto-Scale Y” 

and “Get Trace”,… 

Screen Stacks can be implemented by using control references in one USR and

maintain a screen view stack in another

then implementing actions like “Set Config Screen”, “Set Login Screen”, “Back”… 

Users can be managed using an AE with action such as “Add New User” “Set

Password”, “Disable User”… 

The list goes on and is limited only by our imagination. Here is an example that shows

how a running average can be

maintained.

Page 4: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 4/16

 

Running_Average_Example.jpg

Running Average Example 

The Running Average Example shown above shows how a running average can be

maintained using an AE. The AE is

initialized before the While Loop executes. On each iteration of the loop the simulated

measurement value (random

number) is used to update the history of all measurements (Add Number(s)) and the

mean is calculated (Calc Mean).

Please note that although the buffer of all measurements is affected in every step of 

this example, the buffer (USR in

the sub-VI) contents are never part of this VI’s diagram. Since the history is stored in

the sub-VI, the history can be

Page 5: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 5/16

acted on from more than one thread as shown below.

Parallel_Loops.jpg

In the parallel Loops Example the history is initialized and then two loops run in

parallel with one updating the

history and the other plotting the average. Since the History resides inside the USR of 

the sub-VI the two while loops

are effectively sharing the same block of memory, the block used to store the USR. The

Sub-VI was implemented as shown

in the following sequence of images.

Page 6: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 6/16

 

Init.jpg

As was the case with Functional Globals, the actions are implemented as a type def’d

enum***** driven case structure.Appropriate code is present in each case to realize the intended actions. In the “Init”

case, contents of “Array in” 

are used to initialize the history. In our example above we did not pass an initial array

value. Therefore the “Init” 

resets the history (cleared the array).

Page 7: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 7/16

 

Add Num.JPG

The operation of the AE when the “Add Number(s)” action is called varies depending

on its usage. If the caller passes anon-empty array, it is appended to the array. Alternatively, passing a value via the

Numeric in” control, and leaving 

the “Array in” un-wired adds a single element to the history. We used the Numeric In

input so we were continually

building our history one value at a time.

Page 8: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 8/16

 

Calc_Mean.JPG

When the “Calc Mean” action is invoked, the average is calculated and returned. 

The Traffic Cop Behind the Scenes 

A detail I have not mentioned up until now is that AEs should be implemented as VIs

that are not reentrant***. VIs that are not reentrant can only be executing in one

context at a time. LabVIEW will ensure that if there is ever a situation were two

contexts are attempting to act on the same AE at the same time, LabVIEW will

schedule the first and the subsequent will wait until the first call completes. This is

similar to a traffic cop preventing more than one vehicle from entering an intersection

at the same time. The Traffic Cop is illustrated in the following timing diagram were welook at how the processing of two threads is affected by using a single AE.

Page 9: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 9/16

 

Execution_Timeline.JPG

In the figure above the processing time of two processes “P1” and “P2” are illustrated

by a red or blue solid arrow respectively. In the parallel loops example shown earlier,P1 could be the “Calc Mean” loop and P2 could be the “Add Number(s)” loop. 

t0 - t1 

Both processes are executable and run their assigned tasks. Neither process is

accessing the AE.

t1  – t2 

P2 continues to run while P1 calls the AE. Since the AE is idle it is available to run so P1

continues execution running inside the AE until all work inside the AE completes. The

dotted arrow shows that the thread for P1 is executing in the data space allocated forthe AE.

t2  – t3 

At t2 the AE terminates and both process run as in t0 – t1.

t3  – t4 

This time segment is similar to t1 – t2 with P2 running in the AE.

Page 10: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 10/16

 

t4  – t5 

Similar to t2 – t3 the AE terminates and both process run.

t5  – t6 

Similar to t1 – t2. P1 take control of the AE.

t6 - t7 At t6 P2 attempts to call the AE. Since the AE is not idle it is not available to run. P2 is

placed in a resource wait state (it is NOT running) waiting for the resource to become

available. The dotted horizontal arrow indicates the process is not executing.

t7  – t8 

At t7 the call of the AE by P1 that started at t5 completes and P1 continues to execute

outside of the AE. When the call by P1 completes the AE becomes available. The

process P2 is marked as executable. The scheduler includes P2 in its executable

threads and the AE is available. P2 then executes inside the AE until the call completes.

The Beauty of the AE 

This behavior of a non-reentrant VI is a wonderful feature we can exploit to eliminate

race conditions. Race conditions are the nemesis of many a developer. In hardware

this was solved with clocked enabled logic. In LV we solve race conditions with Queues,

Semaphores, Rendezvous, Occurrences, and Action Engines!AEs can eliminate race

conditions when all operations involving updates of the data stored in the USR are

done INSIDE the AE. A very simple illustration of how the encapsulation of USR

manipulation is shown in the following set of examples.

Page 11: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 11/16

 

Port_With_Global.jpg

This VI is intended to demonstrate how two bits of an eight-bit port can be used to

control the running state of two pumps. To illustrate the control process, one pump

will be set running at start-up and then every half second the state of both pumps will

be toggled to simulate switching of the supply. This example uses globals and fails

miserably.

Page 12: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 12/16

 

Port_With_Global.jpg

In this example we start out by initializing a global variable so that bit “1” (zero based)

is the only bit set in an array of eight bits. This turns on Pump 2 to start. Then the “Port

Update” and a “State Change” loops run in parallel. In the “Port Update” loop the state

of the port is read from the global and used to update the GUI.

In the “State Change” loop, the port status is read and the first Boolean is inverted

before being written back to the global. Similarly for the second Boolean. Since the

read of the globals both occur before the subsequent data processing, one of thethreads will be processing old data.

Page 13: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 13/16

 

Port_With_Action_Engine.jpg

The Action Engine version codes up the same way as the global version but now all of the data manipulation of the port states are encapsulated in the Action Engine “Port

Controller”. This encapsulation ensures all operations involving the data in the USR are

forced to happen sequentially even though we did not have to implement any code to

achieve this affect.

The key point to take away from this example is a shared resource (the port status in

the case) when implemented as AEs come with resource contention resolution built in

provided that all manipulation of the shared resource takes place inside the AE.

Action Engines to the rescue!Action Engines are not a replacement for Queues, Rendezvous and the other

synchronization techniques. They are typically called for when your design dictates

that a single resource must be shared by more than one parallel process and none of 

the LabVIEW provided techniques are sufficient. They require a design of their own to

ensure they work correctly. They also have to be developed and supported.

Wrapping It Up 

After submitting this Nugget for review by my fellow Champions, Jim Kring mentioned

that he wraps up his AE calls in sub-VIs. This is a wonderful way of solving two

Page 14: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 14/16

challenges associated with AE use. The first challenge is not being able to set important

inputs to the AE as “Required”. 

If we develop a wrapper VI for each type of AE call, we can designate all of the

required inputs for proper operation of the AE function call as “Required”. Without

using the wrapper VI to ensure the proper calling convention, the inputs required forANY AE function would be required ALL AE calls.

Example. Suppose you have an AE that stores all of the user information in your

application. Among other functions the AE includes the actions “Set User Password’

and “List all Users”. Since a “User Name” input is required for setting a users password

correctly, this input would be required when attempting to get a list of all of the user

with the “List all Users” action. By wrapping up the individual actions in appropriate

wrapper Vis, we can set the “User Name” input as required in the “Set User Password”

wrapper. The “List all Users” wrapper would not have a “User Name” input. 

A second benefit of using a wrapper VI for each action of the AE is in making

maintenance easier. Since each type of access to the AE is encapsulated its own VI, a

search for a selected wrapper VI is a search for all actions of that type. If you know

there is only one type of action that can cause a condition you are trying to modify,

you can quickly find all of the code that can be affected by changes to that action.

Closing Notes 

1) When using your AE remember the data is in the USR.

2) Let your data define your actions3) Avoid super clusters

4) Hierarchies of AEs help keep your data structures simpler

5) Self initializing and recursive AE are both elegant and efficient

6) AEs do not require a While Loop.

Questions

7) Do you have a process that you go through when designing AEs, what is it?

8) Does anyone use the techniques used for Normalizing Databases to AE design?

9) Do you think that a USR is required for a VI to be considered an AE, e.g. "Could use a

dll call and still call it a AE?"

If you have a Nugget you would like to present please post here to reserve your week!

A list of all Nuggets can be found here. 

I want to offer thanks to Albert Gevens and Jim Kring f or their assistance in creating

this Nugget.

Ben 

Foot Notes*LabVIEW Programming Techniques" produced by Viewpoint Systems Version 2.2

Page 15: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 15/16

August, 2000 page 67. I believe this book was the precursor to the original version of 

NI’s "Advanced Applications Development Course" 

**An Action Engine is generally implemented as a VI that is not reentrant to share the

USR across multiple instances of the sub-VI. A reentrant VI will allocate a unique data

space for each instance of the VI.

***Come on Ben can’t you go a couple of Nuggets with out bringing up reentrancy?

Nope.

**** A “Race condition” is a term used to describe the situation were information

from different sources are not consistent with each other. This term originated in the

hardware of computers were address and control signals could arrive at the inputs of 

chips at different times resulting in the new control state applying to the old address

(for example). In LabVIEW this condition exists whenever there are two writers of an

object (Global, Local, etc) that are executing at the same time.

***** Please see the previous Nugget “Type Definitions Let You See Your Application

in a Different Way” found here .

Type def’d enums are highly recommended for AE development because the case

structures cases will adapt to the enum changes when the type def’s are changed.

When you use enums it is prudent to give some thought to how you want you AE to

respond to new actions being added. If your AE has a action which is not destructive,

e.g. “Read” you can assign it as the default action allowing new action s to be added

without changes to the AE. If every action requires a developer’s attention, then do

NOT define a default action. The AE will break until all of the actions are accounted forby the case structure.

Some minor comments. 

(1) One performance related item is worth pointing out because new users might be

tempted to do things wrong:

It has been discussed very long ago that it apparently makes a significant performance

difference, depending if the terminals of a subVI are placed inside or outside the

structures. "Outside" is better and the given examples are correct in this respect! 

For example, some might be tempted to place the "Numeric in" and "Array in"

terminals inside the "add Numbers" case because they are not really used in the other

cases. Similarly, the "Numeric out" could be placed inside the "mean" case, because it

is the only case that produces meaningful (sic) results for it. These design changes will

probably produce an undesirable performance hit.

Page 16: Action Engine

7/31/2019 Action Engine

http://slidepdf.com/reader/full/action-engine 16/16

 

(2) Some LabVIEW zealots (not necessarily a bad thing) might also point out that the

"array out" is useless because it simply duplicates whatever input arrives at "array in".

In this case it makes no sense to even have that output. Also the "Numeric out" should

be renamed to "mean out" and should produce e.g. NaN in all actions except "calculatemean".

(3) I don't see a problem with the mean of a single number, it gives a well defined

result. We only have a problem if the array size is zero, in which case we should

produce a NaN. This happens automatically so no extra code is needed.

(4) let's also not forget the "first call?" function. Sometimes it can be used to design a

self initializing action engine.