<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Community Nugget 4/08/2007 Action Engines in LabVIEW</title>
    <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/3109024#M891237</link>
    <description>&lt;P&gt;Good.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'll go with those numbers.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Ben&lt;/P&gt;</description>
    <pubDate>Wed, 25 Mar 2015 13:08:04 GMT</pubDate>
    <dc:creator>Ben</dc:creator>
    <dc:date>2015-03-25T13:08:04Z</dc:date>
    <item>
      <title>Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801#M240328</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;Action Engines, What are They?&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;“An action engine is Ben's term for a functional global which includes extra actions other than just holding the data.”&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;(&lt;A href="http://forums.ni.com/ni/board/message?board.id=170&amp;amp;message.id=235297#M235297" target="_blank"&gt;tst , 03-13-2007 01:18 PM&lt;/A&gt;)&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;In a nut shell tst has nailed it except for the “Ben’s term” part. I was originally exposed to the term "Action Engine"&lt;/DIV&gt;
&lt;DIV&gt;by reading the book ""LabVIEW Applications Development A Course on Advanced LabVIEW Programming Techniques*”.&amp;nbsp; But&lt;/DIV&gt;
&lt;DIV&gt;before I get into details of the Action Engine (AE), I will attempt to clarify some terminology.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;Functional Globals&lt;/STRONG&gt;&lt;BR /&gt;Functional Globals (FG) are VIs that are functionally equivalent to LabVIEW globals. Functional Globals store&lt;/DIV&gt;
&lt;DIV&gt;information. You can read them or write them and that is it. No fancy stuff. Functional Globals are also referred to as&lt;/DIV&gt;
&lt;DIV&gt;LV2 globals because LV2 did not have globals but it did support Un-initialized Shift Registers (USRs). The USR is the&lt;/DIV&gt;
&lt;DIV&gt;entity that stores the information.&lt;BR /&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/13/USR.JPG" /&gt;&lt;BR /&gt;USR.jpg&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;USR’s&lt;/STRONG&gt;&lt;BR /&gt;Shift Registers (SR) come in two varieties “Initialized” and “un-initialized”. The presence or absence of a wire&lt;/DIV&gt;
&lt;DIV&gt;feeding the SR from outside the loop distinguishes how LabVIEW will implement the SR. If there is NO wire feeding a&lt;/DIV&gt;
&lt;DIV&gt;shift register (A), then the SR is not initialized. This is called an “Un-Initialized Shift Register”. The USR variety&lt;/DIV&gt;
&lt;DIV&gt;is implemented as static buffer that is re-used from call to call. The values written to the USR in and earlier call&lt;/DIV&gt;
&lt;DIV&gt;persist for access (B) in latter calls**. A Functional Global exploits this behavior by implementing two methods of&lt;/DIV&gt;
&lt;DIV&gt;interacting with the contents of the USR.&lt;BR /&gt;&amp;nbsp;&lt;BR /&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/5/Functional%20Global.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;Functional Global.JPG&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;In the “Write” action (not shown) the value of “Numeric in” is placed in the USR. In the “Read” action the contents of&lt;/DIV&gt;
&lt;DIV&gt;the USR are returned via Numeric out.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;Action Engines&lt;/STRONG&gt;&lt;BR /&gt;An Action Engine (AE) can be thought of as a machine (Engine) that performs some useful task (action) often on&lt;/DIV&gt;
&lt;DIV&gt;something (typically but not limited to data in a USR). Functional Globals are very specific type of Action Engine.&lt;/DIV&gt;
&lt;DIV&gt;They have two actions “Write” and “Read”. They operate on the data stored in the USR either by replacing or using the&lt;/DIV&gt;
&lt;DIV&gt;contents of the USR. So AE’s are a superset of Functional Globals. In many documents the terms AE and FG are&lt;/DIV&gt;
&lt;DIV&gt;interchangeable. A recent &lt;A href="http://forums.lavag.org/index.php?showtopic=2469&amp;amp;st=0" target="_blank"&gt;poll on LAVA &lt;/A&gt;has indicated that Functional Global is the most popular term. Since this Nugget&lt;/DIV&gt;
&lt;DIV&gt;was prompted by answering the question “what is an AE?” in the remainder of this document you will find that I will&lt;/DIV&gt;
&lt;DIV&gt;generally use the term AE.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;Do What to What?&lt;BR /&gt;&lt;/STRONG&gt;AE design revolves around the ways the shared resource must be accessed manipulated or monitored. In a Functional&lt;/DIV&gt;
&lt;DIV&gt;Global, the actions “Write” and “Read” are appropriate. That is not necessarily the case for AEs. AEs can have entirely&lt;/DIV&gt;
&lt;DIV&gt;different set of actions depending on the interaction requirements for the information stored in the USR. A short list&lt;/DIV&gt;
&lt;DIV&gt;follows.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;A Configuration AE could allow for multiple processes to share a single copy of the system configuration (in a USR) by&lt;/DIV&gt;
&lt;DIV&gt;providing actions like “Set Device ID”, Set Device ON-Line…&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;A hardware device can be realized as an AE that presents actions appropriate to the physical phenomenon being measured&lt;/DIV&gt;
&lt;DIV&gt;or controlled.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;A DO Port Controller AE could store a reference to the physical device in one SR and the port status in another SR and&lt;/DIV&gt;
&lt;DIV&gt;have action like: Set Main Motor On”, “E-Stop”, …&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;An Instrument can be implemented to store the device name and settings with actions like “Set Input ON” “Auto-Scale Y”&lt;/DIV&gt;
&lt;DIV&gt;and “Get Trace”,…&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;Screen Stacks can be implemented by using control references in one USR and maintain a screen view stack in another&lt;/DIV&gt;
&lt;DIV&gt;then implementing actions like “Set Config Screen”, “Set Login Screen”, “Back”…&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;Users can be managed using an AE with action such as “Add New User” “Set Password”, “Disable User”…&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;The list goes on and is limited only by our imagination. Here is an example that shows how a running average can be&lt;/DIV&gt;
&lt;DIV&gt;maintained.&lt;BR /&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/12/Running_Average_Example.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;Running_Average_Example.jpg&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;STRONG&gt;Running Average Example&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;DIV&gt;The Running Average Example shown above shows how a running average can be maintained using an AE. The AE is&lt;/DIV&gt;
&lt;DIV&gt;initialized before the While Loop executes. On each iteration of the loop the simulated measurement value (random&lt;/DIV&gt;
&lt;DIV&gt;number) is used to update the history of all measurements (Add Number(s)) and the mean is calculated (Calc Mean).&lt;/DIV&gt;
&lt;DIV&gt;Please note that although the buffer of all measurements is affected in every step of this example, the buffer (USR in&lt;/DIV&gt;
&lt;DIV&gt;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&lt;/DIV&gt;
&lt;DIV&gt;acted on from more than one thread as shown below.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/7/Parallel_Loops.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;Parallel_Loops.jpg&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;In the parallel Loops Example the history is initialized and then two loops run in parallel with one updating the&lt;/DIV&gt;
&lt;DIV&gt;history and the other plotting the average. Since the History resides inside the USR of the sub-VI the two while loops&lt;/DIV&gt;
&lt;DIV&gt;are effectively sharing the same block of memory, the block used to store the USR. The Sub-VI was implemented as shown&lt;/DIV&gt;
&lt;DIV&gt;in the following sequence of images.&lt;BR /&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/6/Init.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;Init.jpg&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;As was the case with Functional Globals, the actions are implemented as a type def’d enum***** driven case structure.&lt;/DIV&gt;
&lt;DIV&gt;Appropriate code is present in each case to realize the intended actions. In the “Init” case, contents of “Array in”&lt;/DIV&gt;
&lt;DIV&gt;are used to initialize the history. In our example above we did not pass an initial array value. Therefore the “Init”&lt;/DIV&gt;
&lt;DIV&gt;resets the history (cleared the array).&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/2/Add%20Num.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;Add Num.JPG&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;The operation of the AE when the “Add Number(s)” action is called varies depending on its usage. If the caller passes a&lt;/DIV&gt;
&lt;DIV&gt;non-empty array, it is appended to the array. Alternatively, passing a value via the Numeric in” control, and leaving&lt;/DIV&gt;
&lt;DIV&gt;the “Array in” un-wired adds a single element to the history. We used the Numeric In input so we were continually&lt;/DIV&gt;
&lt;DIV&gt;building our history one value at a time.&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/3/Calc_Mean.JPG" /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;Calc_Mean.JPG&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;When the “Calc Mean” action is invoked, the average is calculated and returned.&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;This Nugget is continued in the next post&lt;/DIV&gt;</description>
      <pubDate>Sun, 08 Apr 2007 13:37:24 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801#M240328</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-08T13:37:24Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503803#M240329</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;Nugget continued&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The Traffic Cop Behind the Scenes&lt;/STRONG&gt;&lt;BR /&gt;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 we look at how the processing of two threads is affected by using a single AE.&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/1/Execution_Timeline.JPG" /&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Execution_Timeline.JPG&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&amp;nbsp;t0 - t1&lt;/STRONG&gt;&lt;BR /&gt;Both processes are executable and run their assigned tasks. Neither process is accessing the AE.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t1 – t2&lt;/STRONG&gt;&lt;BR /&gt;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 for the AE.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t2 –t3&lt;/STRONG&gt;&lt;BR /&gt;At t2 the AE terminates and both process run as in t0 – t1.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t3 – t4&lt;/STRONG&gt;&lt;BR /&gt;This time segment is similar to t1 – t2 with P2 running in the AE.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/4/Execution_Timeline_t4-t8.JPG" /&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t4 – t5&lt;/STRONG&gt;&lt;BR /&gt;Similar to t2 – t3 the AE terminates and both process run.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t5 – t6&lt;/STRONG&gt;&lt;BR /&gt;Similar to t1 – t2. P1 take control of the AE.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t6 - t7&lt;/STRONG&gt;&lt;BR /&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;t7 –t8&lt;/STRONG&gt;&lt;BR /&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The Beauty of the AE&lt;/STRONG&gt;&lt;BR /&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/9/Port_With_Global._FP.JPG" /&gt;&lt;BR /&gt;&amp;nbsp;&lt;BR /&gt;Port_With_Global.jpg&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/11/Port_With_Global.JPG" /&gt;&lt;BR /&gt;&amp;nbsp;&lt;BR /&gt;Port_With_Global.jpg&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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 the threads will be processing old data.&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/8/Port_With_Action_Engine.JPG" /&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Port_With_Action_Engine.jpg&lt;/P&gt;
&lt;P&gt;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&amp;nbsp; “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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Action Engines to the rescue!&lt;BR /&gt;&lt;/STRONG&gt;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.&lt;/P&gt;
&lt;P&gt;This Nugget is continued in the next post&lt;/P&gt;</description>
      <pubDate>Sun, 08 Apr 2007 13:58:16 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503803#M240329</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-08T13:58:16Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503804#M240330</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;STRONG&gt;Wrapping It Up&lt;/STRONG&gt;&lt;BR /&gt;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 challenges associated with AE use. The first challenge is not being able to set important inputs to the AE as “Required”.&lt;/P&gt;
&lt;P&gt;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 for ANY AE function would be required ALL AE calls.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;&lt;STRONG&gt;Closing Notes&lt;/STRONG&gt;&lt;BR /&gt;1)&amp;nbsp;When using your AE remember the data is in the USR.&lt;BR /&gt;2)&amp;nbsp;Let your data define your actions&lt;BR /&gt;3)&amp;nbsp;Avoid super clusters&lt;BR /&gt;4)&amp;nbsp;Hierarchies of AEs help keep your data structures simpler&lt;BR /&gt;5)&amp;nbsp;Self initializing and recursive AE are both elegant and efficient&lt;BR /&gt;6)&amp;nbsp;AEs do not require a While Loop.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Questions&lt;BR /&gt;&lt;/STRONG&gt;7)&amp;nbsp; Do you have a process that you go through when designing AEs, what is it?&lt;BR /&gt;&lt;span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"&gt;😎&lt;/span&gt;&amp;nbsp;Does anyone use the techniques used for Normalizing Databases to AE design?&lt;BR /&gt;9)&amp;nbsp;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?"&lt;/P&gt;
&lt;P&gt;If you have a Nugget you would like to present please post &lt;A href="http://forums.ni.com/ni/board/message?board.id=BreakPoint&amp;amp;message.id=3194&amp;amp;jump=true" target="_blank"&gt;here&lt;/A&gt; to reserve your week!&lt;/P&gt;
&lt;P&gt;A list of all Nuggets can be found &lt;A href="http://forums.ni.com/ni/board/message?board.id=BreakPoint&amp;amp;message.id=1669&amp;amp;jump=true" target="_blank"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I want to offer thanks to &lt;A href="http://zone.ni.com/devzone/cda/tut/p/id/5269" target="_blank"&gt;Albert Gevens &lt;/A&gt;and &lt;A href="http://zone.ni.com/devzone/cda/tut/p/id/5275" target="_blank"&gt;Jim Kring &lt;/A&gt;for their assistance in creating this Nugget.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://zone.ni.com/devzone/cda/tut/p/id/5277" target="_blank"&gt;Ben&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Foot Notes&lt;BR /&gt;*LabVIEW Programming Techniques" produced by Viewpoint Systems Version 2.2 August, 2000 page 67. I believe this book was the precursor to the original version of NI’s "Advanced Applications Development Course"&lt;/P&gt;
&lt;P&gt;**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.&lt;/P&gt;
&lt;P&gt;***Come on Ben can’t you go a couple of Nuggets with out bringing up reentrancy? Nope.&lt;/P&gt;
&lt;P&gt;**** 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.&lt;/P&gt;
&lt;P&gt;***** Please see the previous Nugget&amp;nbsp; “Type Definitions Let You See Your Application in a Different Way” found &lt;A href="http://forums.ni.com/ni/board/message?board.id=170&amp;amp;message.id=233257#M233257" target="_blank"&gt;here .&lt;BR /&gt;&lt;/A&gt;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 for by the case structure.&lt;/P&gt;&lt;P&gt;Message Edited by Ben on &lt;SPAN class="date_text"&gt;04-08-2007&lt;/SPAN&gt; &lt;SPAN class="time_text"&gt;09:01 AM&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 08 Apr 2007 13:58:38 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503804#M240330</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-08T13:58:38Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503812#M240335</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;Wow Ben, &lt;BR /&gt;&lt;BR /&gt;This is the longest nugget I've ever read. I take my time to read trough it but I'm already sure it's good.&lt;BR /&gt;&lt;BR /&gt;Thank you Ben!&lt;BR /&gt;&lt;BR /&gt;&lt;B&gt;EDIT: &lt;/B&gt;I think you raise an important question about access to shared resources and how &lt;I&gt;action engines &lt;/I&gt;help to deal with access to shared resources. This issue becomes especially important when using shared resources in LabVIEW object oriented programming. If one wants to implement a class level variable similar to C++ or Java static variables, one needs to control the access to this variable somehow to avoid race conditions. Locking a class level variable is not an option as every single object of that specifc class gets locked up. Action engines come in help here as they allow encapsulating action together with a shared resource. So instead of using shared class level variables in LabVIEW object oriented programming, I recommed using class level action engines. &lt;BR /&gt;&lt;BR /&gt;I won't go in to detail on this issue now. I'll be writing an article series &lt;I&gt;Introduction to LabVIEW object-oriented programming&lt;/I&gt; at my blog &lt;A href="http://expressionflow.com" target="_blank"&gt;EXPRESSIONFLOW &lt;/A&gt;(expressionflow.com). This action engine shared class-level resources is an issue I will raise up in this series later on when I've covered enough basics so that this issue is clear for the readers. &lt;A href="http://feeds.feedburner.com/Expressionflow" target="_blank"&gt;Subscribe to the RSS feed&lt;/A&gt; not to miss it.&lt;BR /&gt;&lt;BR /&gt;Tomi&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;&lt;P&gt;Message Edited by Tomi M on &lt;SPAN class="date_text"&gt;04-08-2007&lt;/SPAN&gt; &lt;SPAN class="time_text"&gt;06:26 PM&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 08 Apr 2007 15:06:14 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503812#M240335</guid>
      <dc:creator>Tomi_Maila</dc:creator>
      <dc:date>2007-04-08T15:06:14Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503814#M240337</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;STRONG&gt;Great Nugget. I love the term "action engine".&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Some minor comments.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;(1) One performance related&amp;nbsp;item&amp;nbsp;is worth pointing out because new users might be tempted to do things wrong:&lt;/P&gt;
&lt;P&gt;It has been &lt;A href="http://forums.ni.com/ni/board/message?board.id=170&amp;amp;message.id=191622" target="_blank"&gt;discussed&lt;/A&gt; 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. &lt;STRONG&gt;"Outside" is better&lt;/STRONG&gt; and the given examples are correct in this respect&lt;STRONG&gt;!&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;For example, some might be tempted to place the "Numeric in"&amp;nbsp;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)&amp;nbsp;results for it. These design changes will probably produce an undesirable&amp;nbsp;performance hit.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://forums.ni.com/attachments/ni/130/3196/2/Add%20Num.JPG" /&gt;&lt;/P&gt;
&lt;P&gt;(2) Some LabVIEW zealots (not necessarily a bad thing) might also point out that the "array out"&amp;nbsp; 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 &lt;U&gt;actions &lt;/U&gt;except "calculate mean".&lt;/P&gt;
&lt;P&gt;(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.&lt;/P&gt;
&lt;P&gt;(4) let's also not forget the "first call?" function. Sometimes it can be used&amp;nbsp;to design&amp;nbsp;a self initializing action engine.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 08 Apr 2007 15:46:54 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503814#M240337</guid>
      <dc:creator>altenbach</dc:creator>
      <dc:date>2007-04-08T15:46:54Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503822#M240343</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;/DIV&gt;If you're interested in an improved functional global, you might want to see what LV's new object-oriented programming can do to the functional global. &lt;BR /&gt;&lt;BR /&gt;You can download "the last functional global you'll ever have to write" from &lt;BR /&gt;&lt;A href="http://jabberwocky.outriangle.org/LV2OO_Style_Global_v1.0.zip" target="_blank"&gt;http://jabberwocky.outriangle.org/LV2OO_Style_Global_v1.0.zip&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;Detailed information about the .zip file can be found on page 10 of the PDF file:&lt;BR /&gt;&lt;A href="http://forums.ni.com/ni/board/message?board.id=170&amp;amp;message.id=216094&amp;amp;requireLogin=False" target="_blank"&gt;http://forums.ni.com/ni/board/message?board.id=170&amp;amp;message.id=216094&amp;amp;requireLogin=False&lt;/A&gt;&lt;P&gt;Message Edited by Aristos Queue on &lt;SPAN class="date_text"&gt;04-08-2007&lt;/SPAN&gt; &lt;SPAN class="time_text"&gt;11:33 AM&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 08 Apr 2007 16:31:45 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503822#M240343</guid>
      <dc:creator>AristosQueue (NI)</dc:creator>
      <dc:date>2007-04-08T16:31:45Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503826#M240344</link>
      <description>&lt;DIV&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;P&gt;(2) Some LabVIEW zealots (not necessarily a bad thing) might also point out that the "array out"&amp;nbsp; 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 &lt;U&gt;actions &lt;/U&gt;except "calculate mean".&lt;/P&gt; &lt;HR /&gt;&lt;/BLOCKQUOTE&gt;There is one case where having the array out is a good idea. It's when your array is huge and you want to be sure that no extra buffer copies of the array are made. If you duplicate the wire on the caller block-diagram then there is a risk of an extra and unnecessary buffer copy. &lt;BR /&gt;&lt;/DIV&gt;</description>
      <pubDate>Sun, 08 Apr 2007 18:07:32 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503826#M240344</guid>
      <dc:creator>Tomi_Maila</dc:creator>
      <dc:date>2007-04-08T18:07:32Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503844#M240352</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;&lt;BR /&gt;
&lt;BLOCKQUOTE&gt;
&lt;HR /&gt;
Tomi M wrote:
&lt;DIV&gt;There is one case where having the array out is a good idea. It's when your array is huge and you want to be sure that no extra buffer copies of the array are made. If you duplicate the wire on the caller block-diagram then there is a risk of an extra and unnecessary buffer copy. &lt;BR /&gt;
&lt;HR /&gt;
&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;Are you sure about that? My gut feeling tells me that creating an unneeded output terminal&amp;nbsp;cannot prevent an extra copy. Maybe somebody can make a test VI and see. &lt;span class="lia-unicode-emoji" title=":winking_face:"&gt;😉&lt;/span&gt;&lt;BR /&gt;</description>
      <pubDate>Mon, 09 Apr 2007 00:01:20 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503844#M240352</guid>
      <dc:creator>altenbach</dc:creator>
      <dc:date>2007-04-09T00:01:20Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503849#M240353</link>
      <description>The key word there is "unneeded." Notice in Tomi's post the reference to "if the user branches the array wire..." In other words, the user wants to use the array in the action engine, but also wants to use it in the top-level VI. If you pass it into the AE and keep track of it in a shift register, then the in-placeness algorithm stands a very good chance of being able to use a reference to the array in the subVI instead of making a copy. If you instead branch the wire on the top-level and don't pass the data through the AE, it's very likely LV might have to make a copy.&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 01:16:43 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503849#M240353</guid>
      <dc:creator>Jarrod_S.</dc:creator>
      <dc:date>2007-04-09T01:16:43Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503937#M240383</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;Good Ben,&lt;BR /&gt;Thank you so munch for this Nugget this is the best one I have seen so far in this community.Thanks once again.&lt;BR /&gt;&lt;BR /&gt;CLAD&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 10:44:27 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503937#M240383</guid>
      <dc:creator>ohiofudu</dc:creator>
      <dc:date>2007-04-09T10:44:27Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503945#M240384</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;Well it looks like my concern about addinga section on performance was un justified.&lt;/P&gt;
&lt;P&gt;Thank you for point out the placement of control and how they affect the performance.&lt;/P&gt;
&lt;P&gt;Others have touched on the idea of passing an array through a VI (hopefully by reference) to allow the buffer to be "inspected" by the sub-VI. After the sub-VI completes another function can use the same buffer.&lt;/P&gt;
&lt;P&gt;Christian wrote;&lt;/P&gt;
&lt;P&gt;"&lt;/P&gt;
&lt;P&gt;Also the "Numeric out" should be renamed to "mean out" and should produce e.g. NaN in all &lt;U&gt;actions &lt;/U&gt;except "calculate mean".&lt;/P&gt;
&lt;P&gt;"&lt;/P&gt;
&lt;P&gt;Good point! ...&lt;/P&gt;
&lt;P&gt;unless the AE also offers a "Min" and "Max" function (which this examples does not). &lt;img id="smileywink" class="emoticon emoticon-smileywink" src="https://forums.ni.com/i/smilies/16x16_smiley-wink.gif" alt="Smiley Wink" title="Smiley Wink" /&gt;&lt;/P&gt;
&lt;P&gt;Ben&lt;/P&gt;</description>
      <pubDate>Mon, 09 Apr 2007 11:07:01 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503945#M240384</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-09T11:07:01Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503968#M240398</link>
      <description>Bravo, Ben!&amp;nbsp; Very nice.&amp;nbsp; Thanks.&lt;BR /&gt;&lt;BR /&gt;Matt&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 12:28:36 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503968#M240398</guid>
      <dc:creator>Matthew_Williams</dc:creator>
      <dc:date>2007-04-09T12:28:36Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503969#M240399</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;FONT size="2"&gt;Very nicely-done nugget!&amp;nbsp; FG's and AE's are *very* useful constructs indeed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="2"&gt;Most of my apps involve heavy doses of data acq and I almost always implement an AE around each data acq task (or small set of closely-coupled tasks).&amp;nbsp; This sets me up with 1 common interface to each logical unit of hardware.&amp;nbsp; It has proved to be a pretty effective strategy for re-use as well.&amp;nbsp; The data acq tasks naturally turn into pretty self-contained modules needing relatively little modification from app to app.&amp;nbsp; (Sometimes none at all.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="2"&gt;Like &lt;EM&gt;altenbach&lt;/EM&gt; mentioned, I also almost always use the "First Call?" primitive in any FG to guarantee some kind of initialization.&amp;nbsp; Typically, if the first call performs a "Read" action, I'll catch that fact and provide sensible initialization values.&amp;nbsp; Depending on the FG in question, I may just pass through the default inputs, or I may use special values like NaN, "&amp;lt;undefined&amp;gt;" enum values, or even assert the error cluster --&amp;nbsp;depending on&amp;nbsp;how crucial it is to have initialized *explicitly*.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size="2"&gt;-Kevin P.&lt;/FONT&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 09 Apr 2007 12:34:45 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503969#M240399</guid>
      <dc:creator>Kevin_Price</dc:creator>
      <dc:date>2007-04-09T12:34:45Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503979#M240404</link>
      <description>Some of my early (~LV3) functional globals (had not heard the term Action Engine then) had a Valid output.  It remained False until a Write had occurred and was reset to False if the Reset action was performed.&lt;BR /&gt;&lt;BR /&gt;Nice job, Ben.&lt;BR /&gt;&lt;BR /&gt;Lynn</description>
      <pubDate>Mon, 09 Apr 2007 13:13:58 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503979#M240404</guid>
      <dc:creator>johnsold</dc:creator>
      <dc:date>2007-04-09T13:13:58Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503983#M240408</link>
      <description>Nice job, Ben.&amp;nbsp; I have one more performance improvement that only is worth considering if you are using the AE to store a dynamic array and you are adding data to or subtracting data from the array frequently.&amp;nbsp; It results in code which is quite a bit more complex.&lt;BR /&gt;&lt;BR /&gt;Build array is a very expensive operation due to using the memory manager and, if used repeatedly, can fragment memory, causing more performance issues.&amp;nbsp; You need to create some sort of memory management so you don't keep hitting the build array primitive, and the AE allows you to do this.&amp;nbsp; The executive summary - when you initialize the array, always create twice as many data points as you need, and a minimum of 8 to 16 points.&amp;nbsp; Keep track of the number of points actually used and the number available.&amp;nbsp; When you add points to the array, if you need more space, double the array size.&amp;nbsp; If you subtract data from the array, halve the size if you get to less than one quarter of the points actually used.&amp;nbsp; Note that actual increases and decreases should be tweaked for your application.&amp;nbsp; Operations such as min, max, and average may be more efficiently done when points are added (although that is a performance issue each application will need to work out).&lt;BR /&gt;&lt;BR /&gt;If I have a chance, I will code it up and post it.&amp;nbsp; I have used this in the past with dramatically better performance, but details count, and any particular problem may or may not benefit from such an approach.&amp;nbsp; The time you save adding points may be lost when processing them, since you cannot use the array operations without creating a subset of the array, which hits the memory manager and may cause a copy.&amp;nbsp; The best way around this issue is processing the points as you add them, but you can easily end up losing any performance gain you got by not hitting the memory manager.&amp;nbsp; Of course, you sort of get the performance back on the read, since the values already exist.&lt;BR /&gt;&lt;BR /&gt;Your mileage may vary...&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 13:19:44 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503983#M240408</guid>
      <dc:creator>DFGray</dc:creator>
      <dc:date>2007-04-09T13:19:44Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504009#M240422</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;Hi All,&lt;/P&gt;
&lt;P&gt;I will try to reply to the replies in chronological order as time permits.&lt;/P&gt;
&lt;P&gt;Tomi,&lt;/P&gt;
&lt;P&gt;Now that this Nugget is out of my head I will look into harnessing the LVOOP ideas you have been pushing. I'll reply back with this.&lt;/P&gt;
&lt;P&gt;Aristos,&lt;/P&gt;
&lt;P&gt;I WILL have to follow-up on your link. Concidering how much time I spend with AE's your comments are very tempting!&lt;/P&gt;
&lt;P&gt;I will reply to the other posting when I get a break.&lt;/P&gt;
&lt;P&gt;Thank you!&lt;/P&gt;
&lt;P&gt;Ben&lt;/P&gt;</description>
      <pubDate>Mon, 09 Apr 2007 14:14:13 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504009#M240422</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-09T14:14:13Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504070#M240450</link>
      <description>&lt;DIV&gt;&lt;/DIV&gt;
&lt;P&gt;Tomi Stephan and others,&lt;/P&gt;
&lt;P&gt;To get my head around how to think LVOOPishly, I appreciate a little help.&lt;/P&gt;
&lt;P&gt;In my Action Engines...&lt;/P&gt;
&lt;P&gt;Should I understand the data in the USR to be a class or is the cluster that defines the USR contents that I should think of as a "Class"?&lt;/P&gt;
&lt;P&gt;If I perform an action that modifies the USR, is that a "method"?&lt;/P&gt;
&lt;P&gt;If I just read out the "average" is that a "property"?&lt;/P&gt;
&lt;P&gt;Ben&lt;/P&gt;</description>
      <pubDate>Mon, 09 Apr 2007 15:52:26 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504070#M240450</guid>
      <dc:creator>Ben</dc:creator>
      <dc:date>2007-04-09T15:52:26Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504072#M240451</link>
      <description>To follow up on DFGray's comments, I usually keep a pointer (in the AE) to the next available location in the AE array.&lt;BR /&gt;When the pointer = array size, time to go get more array elements.&amp;nbsp; If you allocate in 100 entry chunks your memory &lt;BR /&gt;manager overhead is decreased by ~99%, with modest over-allocation.&amp;nbsp; Works very well for typical AE array sizes we &lt;BR /&gt;work with, hundreds to low tens-of-thousands elements.&lt;BR /&gt;&lt;BR /&gt;Matt&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 15:56:31 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504072#M240451</guid>
      <dc:creator>Matthew_Williams</dc:creator>
      <dc:date>2007-04-09T15:56:31Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504093#M240460</link>
      <description>It seems to me the entire FG would constitute a class, since a class is not only stored data but the functions that operate on that data. The cluster in the USR is your private data, since it obviously can't be accessed outside the FG without accessor methods.&lt;BR /&gt;&lt;BR /&gt;Reading a property would simply be outputting a data value that is stored in the USRs. This could include one element out of a cluster. If you are storing your average in the USR and you just want to output it without recalculating it, then yes, that could be a property. If you include the act of calculating it, that sounds more like a method.&lt;BR /&gt;&lt;BR /&gt;The analogy with LV2-style Functional Globals and classes seems to break down when you start talking about inheritance, because there's no automatic way to inherit a FG and get all its data and methods along with your own new child data and methods. You would have to modify the original functional global to extend its functionality in such a way.&lt;BR /&gt;&lt;DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 16:48:03 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504093#M240460</guid>
      <dc:creator>Jarrod_S.</dc:creator>
      <dc:date>2007-04-09T16:48:03Z</dc:date>
    </item>
    <item>
      <title>Re: Community Nugget 4/08/2007 Action Engines</title>
      <link>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504100#M240463</link>
      <description>&lt;DIV&gt;&lt;BR /&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;P&gt;Should I understand the data in the USR to be a class or is the cluster that defines the USR contents that I should think of as a "Class"?&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;I haven't had time to take a look for Stephens example so I will not talk for Stephen but only for myself. The USR could be but would not neet to be an object in LabVOOP. It can as well be anything else such like in pre-LabVOOP LabVIEW. The more relevant question is if the USR containst the class type the VI (method) belongs to or something else. However the story is too long to be replied here wihtout much too many references to undefined issues. I'd rather go on my introduction to LabVIEW object-oriented programming &lt;A href="http://expressionflow.com" target="_blank"&gt;in my blog at expressionflow&lt;/A&gt;. When the time is right I'll talk about functional globals and action engines in contexto of object-oriented programming.&lt;BR /&gt;&lt;BR /&gt;My advice, it's very hard to wrap you head around object-oriented programming without actually reading something. The easiest way would be to follow my blog for some time. The more challenging way would be to read one or more books on OOP in the context of some other programming language such as Java.&lt;BR /&gt;&lt;BR /&gt;Tomi&lt;/DIV&gt;</description>
      <pubDate>Mon, 09 Apr 2007 17:05:45 GMT</pubDate>
      <guid>https://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/504100#M240463</guid>
      <dc:creator>Tomi_Maila</dc:creator>
      <dc:date>2007-04-09T17:05:45Z</dc:date>
    </item>
  </channel>
</rss>

