Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Is this state-handling a correct way to manage messages? (Concrete example of theoretical AOD principles)

Solved!
Go to solution

I have been reading the explanation of AOD principles. Once in a while, I will even read one of the referenced documents. Most of the references are too theoretical for my hardware-based mind to grok. Most of what I know about LabVIEW was learned by copying examples and by fixing problems. AQ's sample AF projects are very useful. I wonder if it would also be useful to compare traditional with AF. For example, the Boiler CLD sample-exam. I kept the event structure in Actor Core very simple - it basically just sends messages to actor methods upon user input. Only Stop Core.vi sends the Stop UI event:

4-11-2013 11-24-19 AM.png

UI indicators are updated via a single user event:

4-11-2013 11-27-11 AM.png

This event is only generated in a single Protected actor method. Note that the state of the cluster is maintained in the Actor's private data:

4-11-2013 11-35-37 AM.png

So far, I don't think anything is odd - just a choice. What I am concerned about is the "State" of the actor. I keep a typd-def enum in the actor's private data. Some methods set this state after doing things:

4-11-2013 11-39-40 AM.png

Some methods avoid setting the state, but they send a message which calls another method that changes state:

4-11-2013 11-41-31 AM.png

How do I know whether the current state gets "stepped on"? When a message is sent to self from within a method (at the same priority), someone else (like button presses on the UI) can still send messages to self. When people say the actor decides whether to process a message, is state-testing one way to do that? Are there other ways?

Note that there is a Log File Actor, but there are no "responses" in this example - only requests.

Source can be found here:

http://forums.ni.com/t5/Certification/Sample-Exam-Solutions-for-Review/m-p/2385580#M738

Thanks for any help.

0 Kudos
Message 1 of 6
(4,867 Views)

Todd_Lesher wrote:

Some methods avoid setting the state, but they send a message which calls another method that changes state:

Why not just call the method directly?

Todd_Lesher wrote:

When people say the actor decides whether to process a message, is state-testing one way to do that? Are there other ways?

You have to create a filter actor and send messages to a nested actor.  There is a pretty good discussion on this at http://lavag.org/topic/16607-actor-queue-relationship-in-the-actor-framework

I would also take a look at Norm's Rebirth of the LabVIEW State Machine.  The same risks and solutions apply to the Actor Framework.

CLA, CTA
Message 2 of 6
(3,476 Views)

LVB wrote:

Todd_Lesher wrote:

Some methods avoid setting the state, but they send a message which calls another method that changes state:

Why not just call the method directly?

Oh, good idea.

Todd_Lesher wrote:

When people say the actor decides whether to process a message, is state-testing one way to do that? Are there other ways?

You have to create a filter actor and send messages to a nested actor.  There is a pretty good discussion on this at http://lavag.org/topic/16607-actor-queue-relationship-in-the-actor-framework

In that thread, AQ said a "secretary" is one way, but that maintaining state in the receiver is another way. I haven't found any examples of maintaining state in the receiver.

I am not averse to a secretary. I would prefer something along the lines of Paul Lowell's State Pattern, implemented with something along the lines of - oh, can't find the link, now - the one where the the "transports" were all sub-classed to ensure delivery only to specific actors.

However, I've been using small actors in the middle of "traditional + LVOOP" code, and they are handy. I've also been using actors for somewhat simple apps, almost along the lines of the CLD sample exams. To me, it is a lot simpler to change the functionality in an AF version than in the suggested exam solutions. I am aware that some people think the exams are not indicative of real-world apps. That doesn't mean I can't use them to learn .

LVB wrote:

I would also take a look at Norm's Rebirth of the LabVIEW State Machine.  The same risks and solutions apply to the Actor Framework

Yes, I have TLB' and have watched his presentation at least once. I like TLB'. So far, AF just fits better in my head, as far as abstraction and modularity. In general, I've been looking for more examples. Specifically, at the moment, I'm interested in State, and whether the example I wrote violates any best practices.

0 Kudos
Message 3 of 6
(3,476 Views)

Todd_Lesher wrote:

LVB wrote:

Todd_Lesher wrote:

Some methods avoid setting the state, but they send a message which calls another method that changes state:

Why not just call the method directly?

Oh, good idea.

You can also, if you have a written message for yourself, call "Do.vi" on it directly rather than sending it.  Helpful if your messages call multiple methods or have extra code in them.

BTW, one reason I mentioned the "ACID" principles of database transactions in another thread is for cases like this, where a message enqueues another message to itself.  Executing the second message directly, rather than enqueuing it, allows the two messages to be a single atomic operation that is isolated from all other possible operations, and the first message is relieved of the burden of having to leave the actor in a consistant state. 

Message 4 of 6
(3,476 Views)
Solution
Accepted by Todd_Lesher

Todd_Lesher wrote:

When people say the actor decides whether to process a message, is state-testing one way to do that? Are there other ways?

There are two main techniques I am aware of that you can use to implement message filtering.  Data-state testing is the easier technique.  With data-state testing when the actor receives a message, it checks the value of a data field and uses that value to decide how to handle the message.  The data field it checks could be anything:  a boolean flag, an integer, an enum defining the actor's behavioral states, etc.  Conceptually, it's not even required for the data field to be stored locally by the actor.  It could be in a database, or another actor, or in the cloud.  (I would tread very carefully if trying to implement message filtering based on non-local data.  It's definitely not something to take lightly.)

The other technique is to use dynamic dispatching to swap the entire message handling code base at runtime.  In the AF, you could create child classes for your Actor for each behavioral state and implement the unique message handling code in those.  At runtime when conditions trigger a behavioral state change you spin up the appropriate child Actor and replace the current one.  In a case-structure message handling system you don't need to replace the entire actor.  You can create a class hierarchy for each behavioral state and/or a class hierarchy for the message handlers.  The decisions depend on the exact nature of the state diagram you are implementing.

The AF seems to more naturally align with data-state testing and case-structure actors seem to more naturally align with dynamically swapping the message handling code.  Both message filtering techniques can be used with either style of actor.

LVB wrote:

You have to create a filter actor and send messages to a nested actor.

Filter actors can be used but there is a huge flashing neon caveat that goes along with them:

The nested actor must be behaviorally sound.**

"Behaviorally sound" is a new term I just made up, and it means the actor is never in a condition where receiving the "wrong" message will cause it to do something unexpected.  You cannot use a filter actor to turn an unsound actor into a sound actor.  It is, as far as I can tell, impossible.  (This idea is very much a work in progress and represents my current thinking.  As with all of my opinions, it is subject to change as I obtain new information.)

The obvious question is, since message filtering is what makes an actor behaviorally sound, and the nested actor must be behaviorally sound prior to using a filter actor, what's the point of the filter actor?  In essence the filter actor is an organizational technique.  It wraps the nested actor and presents its functionality as behaviorally stateful even though it is not inherently behaviorally stateful.  I can imagine scenarios where it would be beneficial to do that (i.e. if other actors need to use an instance of the nested actor without statefulness,) but in most cases I think the filter adds unnecessary complexity.  If your system needs the nested actor to present behavioral statefulness, build that into the nested actor itself and skip the filter.

<Edit - Heavily theoretical stuff>

**(10 minutes after posting I realized this is not strictly true.  It is possible for the nested actor to be behaviorally unsound--meaning it will process "incorrect" messages that cause unintended behavior--as long as the filter actor doesn't send any "incorrect" messages.  However, any time the nested actor's de facto behavioral state changes (i.e. the set of "correct" messages the nested actor can process) the filter actor needs to wait for an acknowledgement of the new state before sending a potentially "incorrect" message.  This ability requires the filter actor to have intimate knowledge of the nested actor's implementation, and seems to violate all sorts of principles of encapsulation.  I believe it is still strongly preferably to make the nested actor behaviorally sound.)

</theory>

Todd_Lesher wrote:

In that thread, AQ said a "secretary" is one way, but that maintaining state in the receiver is another way. I haven't found any examples of maintaining state in the receiver.

Todd_Lesher wrote: 
I keep a typd-def enum in the actor's private data.

Keeping a typedeffed enum in the actor's private data is a perfectly valid way to maintain state in the receiver.  Hopefully you have the state diagram documented somewhere so other users don't have reconstruct it from code.    Comment boxes and the arrow decorations work in a pinch.

Message was edited by: Daklu

0 Kudos
Message 5 of 6
(3,476 Views)

Thanks, all, for the replies.

Daklu, I'll stick with data-state testing, for now. "Easier" is appealing - at least until I get a few iterations coded up. (And documented - Ha!)

0 Kudos
Message 6 of 6
(3,476 Views)