Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Self-Messaging and Messages with Output

Solved!
Go to solution

I have an application that I am developing using AF. I have only limited "practical" experience with OO programming, but I have spent quite a bit of time educating myself and can hopefully speak dangerously (if not intelligently) about this material. I have played with the Evaporative Cooler example provided with LV2012 and have found it useful in understanding many features of AF. I've got a couple of questions regarding coding according to the design intent of AF, so that I'm not wandering outside the bounds of the framework. I'm not skilled enough to venture into stretching those boundaries yet.

Hopefully my questions won't be repeats of previous questions... I skimmed previous discussions and didn't find exactly what I was looking for. Here goes!

Based on the whitepaper provided along with the Evap Cooler example, I have chosen to create a set of user events to manage updates to an actor's front panel. The goal is to be able to control this actor via the framework (as a nested actor) or as a standalone actor (if the rest of the actors in my system aren't necessary for a task specific to this single actor to be accomplished). Since the framework allows each VI to run independently, this seems like a reasonable thing to want to do. Before launching the actor, these user events are created and then bundled into a cluster and stored as part of the actor's private data.

These user events are dynamically registered by an event event loop that runs in parallel with the Call to Parent in Actor Core.vi. In order to provide a "common" interface for local/remote operation, the actor front panel controls generate static events that subsequently trigger the user events. This means that I don't have to provide a caller with any control references, it simply needs to know what events to generate. Maybe this ends up being semantics, but it seemed "cleaner" to me to do it this way.

Is there a question coming, you ask? Yes. The first one is coming (it's underlined).

Each event that is triggered is intended to run a bit of code responsible for changing the behavior of the actor. Should these bits of code use actor methods directly or should they employ "self-messaging"? What I mean by self-messaging is wrapping a method in a message that gets sent on the actor's self-queue. Self-messaging seems to allow for an approach that is more consistent with the framwork's intention as stated in the whitepaper, namely "Use message objects to modify the state of an actor object."

With the first approach, I could pass an actor object into the event loop and simply call methods directly. This seems to have the advantage of easier access to outputs for those methods that produce them. The disadvantage is that when the actor is stopped, the event loop still has events to execute (before the stop event can be handled). This means all method calls will throw an error, because the actor is no longer running. I could handle that error explicitly in my code, but that seems inelegant. I'm not sure if there's a way to prioritize events (they seem to be handled FIFO), so I can't push a stop event in front of all the others that will throw errors.

So there's another question that I'm looking for an answer to:

How does one handle a message that invokes a method that produces output? One way, certainly, is that the output is stored inside the actor's private data, so the message can invoke a write accessor method. This still doesn't really help, because if I stick with the paradigm of only using messages in my parallel event loop, I don't understand how to get the data out of a message that invokes the read accessor method. A potential complication here is that I'm not really sending the data to a caller actor, I'm sending it to the actor itself.  The whitepaper has a comment about sending asynchronous replies using a wrapper around the VI that has outputs, but the details are insufficient for me to understand how to execute the next step.

If I've missed something significant or said something crazy, please be gentle. I look forward to any and all replies.

Kind regards!

0 Kudos
Message 1 of 7
(6,741 Views)

Self messaging:

You can't really pass the actor into the event loop. You would pass a *copy* of the actor into the event loop, but objects are passed by-value -- fork the wire and you have two separate objects. So, yes, self-messaging is what you have to do in order to talk to the actual instance of the actor which is sitting in the parent method. Any attempt to do otherwise will have your methods acting on object state that knows nothing about all the other messages that were sent in the system.

Methods with outputs:

If you design for actors from scratch, you don't generally have outputs from public (i.e. messagable) methods. The behavior inside the method is to send a response to some other actor. If you're adapting an existing class to be an actor, you may have outputs, in which case the Do.vi method that called the method needs to package up the outputs into a new message and send it some where -- generally back to the actor that sent the original message. If your actor doesn't have any nested actors of its own and you've respected the actor tree (i.e. callers never share their nested actor queues with any other actor), then you can just unconditionally fire a new message up to the caller saying, "Here's the results of that method call that you asked for a while back". Note that you could use a Reply Msg to do this, but I generally recommend never using the Reply Msg unless you've run out of other options because even when Reply Msgs don't cause deadlocks (which they can if abused), they cause the caller to wait on nested activities, meaning the caller becomes unresponsive in the meantime. Leads to missed data signals and laggy user interfaces.

If your actor does have nested actors or you have shared actor queues around, then it is ambiguous who to send the reply to. In that case, the original sender will need to include its send queue in the original message so that the Do.vi knows who to whom to send the answer back.

Message 2 of 7
(4,082 Views)

PS: If anything I've written above helps elucidate the white paper, please feel free to post recommendations for how to improve that document. We can include changes in the next version of LabVIEW for future users.

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

1.  You want to use the "Read Self Enqueuer.vi" to get the actor's own queue.  Then have the events put messages on that queue.

2.  You want to build your program where an actor (caller) will call other actors (callee) and store their queues for when it needs to send messages to them.  The actors (Callee) that get launched will use the "Read Caller Enqueuer.vi" to send messages back to the program that called them.  You want to use the Zero Coupling paradigm here.  The callee will have a reply message type in its private data.  This is a parent class from which the caller will need a child class that inherits from that parent class.  When the caller launches the callee it will write the child message class to the callee's private data.  When the callee replies it will store data in the parent class, and it is in fact unaware of what the child class message is.  It will then send the data to the caller.  Again, what makes this powerful is that the callee doesn't need to know who the caller is.  The caller knows what data the callee will send back.

Good luck.  Invest the time in learning how this works.  It is worth it.

Casey

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

0 Kudos
Message 4 of 7
(4,082 Views)

Thanks much for taking the time to answer my questions. The first looks straightforward: use messages exclusively for communicating with a running actor, even when the actor communicates with itself.

The second makes sense, but in the case of self-communication, is the only way to get the data contained in the reply message to make that data be a part of the actor's private data? Can there be such a thing as a private message, accessible only by self-communication?

0 Kudos
Message 5 of 7
(4,082 Views)

1. In general, this has been my strategy.

2. The architecture you suggest is precisely what I have setup. The main issue here is that I want an actor to have the ability to "stand-alone," as well as be called by another actor. This means that I have tried to build the internal interfaces in such a way that the actor interacts with itself with precisely the same methodology as it would with a caller actor.

Thanks for the verification and encouragement. I still have a lot to learn!

0 Kudos
Message 6 of 7
(4,082 Views)
Solution
Accepted by topic author munsmat

munsmat wrote:

The second makes sense, but in the case of self-communication, is the only way to get the data contained in the reply message to make that data be a part of the actor's private data? Can there be such a thing as a private message, accessible only by self-communication?

Private messages: Let's say you have an actor named X.lvclass. If you create a library named X.lvlib, you can place your class in that library. Then you can place a message class also in that library. Then mark the message class as Private. Now it cannot be accessed outside the library -- so the Actor (which is inside the library) can send that message to itself, but no one else can send it.

Getting data from yourself in another loop in your Actor Core: So, you have some loop (often an event loop, but not always) running in your Actor Core.vi. You can send a message to yourself to say, "Do This Action". Now you want to get a reply from that message. You have a couple options:

1) When Actor Core.vi starts running, create a refnum (notifier, queue or user event, usually, but perhaps you have some other favorite signaling mechanism) and store it in the private data of the actor object *before* you pass it into the Call Parent Node. Then when the "Do This Action" method executes, it can use that embedded refnum to signal the other loop.

2) When you send the "Do This Action" message, include in the message a refnum (as above) that is used to signal a finish.

Option 1 is generally more efficient since you can reuse the same refnum over and over again, but option 2 is useful if other actors are going to be able to send the same message (i.e. if the message is not a private message).

If you use option 2, you can save yourself some programming and create a new child class of Reply Msg, but I would ONLY do that if it is a private message. Why? Because the inner loop of your own Actor Core.vi is not in charge of processing messages and so it holding and waiting on the message handling loop isn't generally a potential deadlock... at the very most, it is one that you can design for consciously. If this is a public message, I would use something that can be polled occassionally rather than waiting.

Minor point: The part about private messages is directly in the help document. The messaging to self is discussed, but perhaps needs fleshing out. Please check those sections and let me know if you have suggestions for improving.

Message 7 of 7
(4,082 Views)