Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

How does AF handle continuous execution of some action?

Solved!
Go to solution

I do the continous execution in a different way. I guess it is the same way that you find ugly, however I find it very similar to the parallel loop solution.

So I create one method in my actor class that is equal to one iteration of the loop (If we would make a parallel loop). I make one message that usually has no message data, because my Iteration method also has no input (If you feel like you can have inputs to it). This message executes this iteration method in it's Do.vi.

I send this "iteration" message as the last step of my Iteration method. If you want to handle stop conditions, you can decide with a case to send the "iteration" message or the Stop message.

It has the following advantages:

- You have access to all the private datas of the Actor, so handling state changes - what you wanted to do - becomes easier.

- A Stop message coming from another actor also stops the actor easily.

- No possibility of an un-stoppable loop (if one iteration is finished in foreseeable time), as the main actor can always send a Stop message.

Disadvantages:

- you have to send one empty message. I really don't know how much, but it's obvious that it's at least a bit overhead, because LabVIEW has to handle the message handling. (One LabVIEW expert could comment on this.)

- not so easy to see the loop, however you can get used to it.

- To test you obviously need an actor based test environment. However if you do it for some time, you will find pattens and templates that are reusable.

0 Kudos
Message 11 of 34
(1,718 Views)

all I've seen is that you could do it by having the process enqueue itself to the actor, but this seems really ugly to me (similar to Daklu's aversion to the QSM which enqueues to itself).

Consider your process which has three proposed states: Idle, Read Position, and Control on Position.  What is the aversion to sending these messages to self?  It is no different than a simple QDSM Queue and Enum loop...

Once the process is moved to a parallel loop in the Actor Core.vi override, things like handling and syncronizing data become more difficult.  There are a few cases that require a parallel loop (Timed Loop, Reading Buffered Data, ...).  What are you gaining by creating the parallel loop? 

Another big design decision is based upon how the "continuous process" needs to share and obtain its data (position).  There are many considerations:

  • What is your process doing?
    • Is Control on Position a PID loop?
  • Is there a required dwell or loop rate for reading/controlling position?
  • How long does it take for a Read/Control command?
  • How and what data is the actor sharing?
CLA, CTA
0 Kudos
Message 12 of 34
(1,718 Views)

Why use a SEQ instead of a DVR? When I want to send an object to a parallel loop I create a different class that has as its private data a DVR that wraps the original object.

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 13 of 34
(1,718 Views)

I want control to continue a time-critical sense. I can't afford to have the actual control broken up by whatever requests the actor is receiving from its caller.

0 Kudos
Message 14 of 34
(1,718 Views)

Isn't one of the intended uses of the "Time-Delayed Send Message" VI to schedule future updates of continuous processes within an Actor?

-- James

BTW> a related post by Daklu on LAVA about how he handles continuous processes with his actor-like system.

Message 15 of 34
(1,718 Views)

They achieve the same result for basic use, so his choice of API is really pretty irrelevant. But here are some reasons not to use a DVR for all situations:

  • DVRs can't be backed-saved to many old versions. (I think they were released in 8.6?)
  • DVRs have no method of previewing the content. You have to pop the item from the DVR to look at it.
  • DVRs have no timeout. This one is really important, because it means they can easily create deadlocks in your application by waiting for eternity to gain access to the reference while something else has it.
0 Kudos
Message 16 of 34
(1,718 Views)

"Time-critical" execution usually just means designing your process to execute within a certain window every time. It requires the ability to schedule threads and guarantee there are no lock-outs or waits in the critical path. It doesn't really mean that you have to write something that can't be interrupted though, and unless you're throwing together a quick-n-dirty concept program, you're 90% likely to need to be able to interrupt the code with a message so you can stop it or change its behavior.

Anyway, even LVRT's Timed Loops handle time-critical code by simply reporting whether the previous iteration completed in the allowed window. It's your responsibility to handle the situation when it doesn't. I would design my time-critical code in the same manner, checking iteration [i-1]'s elapsed time and making decisions for iteration based on the result.

0 Kudos
Message 17 of 34
(1,718 Views)

LVB wrote:

What is the aversion to sending these messages to self?  It is no different than a simple QDSM Queue and Enum loop...

Ayup... and therein lies the problem.

In principle there is nothing wrong with having a loop send a message to itself.  In practice, based on the code I have seen over the years, it is very easy to introduce subtle race conditions that may not be apparent or discovered until it's too late.  QSMs often use "states" where sub vis are more appropriate.  That's what makes them dangerous.  The "states" must execute in a specific order.  If the expected sequence is disrupted unpredictable things happen.  Usually that's bad.  Sending messages to self makes it easy to introduce unintentional sequential requirements that can't be enforced.

If you don't allow the loop to send messages to itself, you can't queue up a bunch of operations to perform.  You're forced to create atomic message handlers and sub vis.  A properly written message handling loop can receive any message at any time and react in a predictable and known way.  As long as your messages are atomic and there are no message sequence expectations in the receiving loop, you can safely send messages to self.  Unfortunately, the idea of atomic messages isn't widely known in the LV community, so often when I encounter self-sent messages there is also an unintended message sequence requirement in the receiving loop.

0 Kudos
Message 18 of 34
(1,718 Views)

GotRobotFriends wrote:

I want control to continue a time-critical sense. I can't afford to have the actual control broken up by whatever requests the actor is receiving from its caller.

The link James posted shows two techniques I've employed.  I use a metronome (called a "heartbeat" in the post) when I need to execute some process at periodic intervals.  If the process has to be more or less continuous, I separate the message handling loop from the continuous loop and share data between them.  (The "DVR" option in the post.)

Note that my DVR option doesn't have a message handler.  I have found it easier in the long run to restrict each loop to a single mechansim for getting data from outside sources.  For the Image Rendering loop in the DVR option, that mechanism is the DVR.

0 Kudos
Message 19 of 34
(1,718 Views)

Then I especially recommend creating a parallel loop within a child actor core.

Elijah Kerry
NI Director, Software Community
0 Kudos
Message 20 of 34
(1,718 Views)