Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Auto-stopping dynamically launched nested actors

Thank you for taking a look at the problem. This is helpful discussion.

(1) This example showcases what I think people are getting caught up on. In my original code I passed in the object itself to the while loop. One reason for that is that the Launch Nested Actor.vi required the actor class. Once I fixed it by using the "Send Launch Nested Actor Msg.vi" I left it as is and just got the enqueuer out from the class, as that was all that was needed anyway to send a message. I think this has confused people because they think I was trying to use that as the actor object. In either case, the actor object is branched, and it's semantical to talk about getting the enqueuer reference from outside or inside the loop. Getting it inside led people to believe something else was happening, but that is what's required by the Launch Nested Actor.vi! So that's again my point. In the case of dynamically launching actors, you are lead astray by the default behavior that almost anyone will try first.

(2) Your second point is a great point, and one I hoped people would see by going through the code path. It doesn't make my point moot though. It drives it home!

See there, the "Launch Nested Actor.vi" gets called on the actor object in the right context, i.e. in the context of the parent Actore Core.vi running the messaging while loop. It is called as a method that is generated by a message, so that its updating of the actor object goes back into the parent Actore Core.vi while loop. And that's why it works where the "default" way doesn't. Look into the Actor.lvclass:Actore Core.vi to see this while loop that waits on messages. Once this loop receives the "Launch Nested Actor Msg", it runs the methods on the class, and returns it to the shift register in the while loop. So it correctly updates and persists the Nested Actors property. Then when this actor class getting passed around in the shift register gets the stop message, it has the appropriate Nested Actors to call stop on. In the default way, the Nested Actors property value never gets to this object in the Actore Core.vi loop which is the actual running actor!

(3) The only reason any of this came about was because of the auto-stop behavior. This behavior, as currently implemented the way it is, requires this discussion I think. If other languages do things different or in a better way, I think that discussion would apply here. My whole point was that I wanted dynamically launched actors to be launched the correct way (whatever that is, I found "a" way) and wanted auto-stop to work (I also found "a" way). But I found the "default" Launch Nested Actor.vi to be misleading in the dynamic actor case in addition to it not working properly.

0 Kudos
Message 21 of 34
(1,940 Views)

bmitchell wrote:

Brainstorms wrote:

When the "Launch Nested Actor" in your DD "Default behavior" case runs and launches the nested actor, the root actor's "actor object copy" wire that receives the resulting enqueuer is not wired to the output of "Launch Nested Actor.vi"...  So the object copy containing goes nowhere... and LabVIEW's garbage collector reaps it and it's gone.

And once it's gone, it's gone, and that means "There's no way to talk to the nested actor any longer."  I.e., you can't stop it.  (Or do anything else useful with it.)

That is entirely my point and an explanation of the pathological behavior in the Launch Nested Actor.vi. This is the behavior I do not like. It shouldn't be doing this.

No, it should be doing this.  Launch Nested Actor takes an Actor object, which in the AF is the by-val internal state data of the Actor.  It's standard LabVIEW that methods on by-val data must be called on that data, not a copy (with the exception of reading an unchanging thing, like the actor's Engueuer).  In the Actor Framework, methods that asynchronously interact with the Actor after it's launch all take an Enqueuer object (and they usially have "Send" in the name).

One might argue there is a naming problem: talking about the "Actor" makes most intuitive sense as being the asynchromous process, but in the AF the "Actor object" is actually the internal state data of the Actor along with methods of this internal state.  It might have been better to call this something else, like "Actor State" or "Actor Data".   The "Enqueuer" object might be better thought of as "the Actor" or, at least, the "Actor Ref".

0 Kudos
Message 22 of 34
(1,940 Views)

One might argue there is a naming problem: talking about the "Actor" makes most intuitive sense as being the asynchromous process, but in the AF the "Actor object" is actually the internal state data of the Actor along with methods of this internal state.  It might have been better to call this something else, like "Actor State" or "Actor Data".   The "Enqueuer" object might be better thought of as "the Actor" or, at least, the "Actor Ref".

Personally I think it's much better to think of the enqueuer as the actor mail-box, or at least "the place where you put messages for the actor" i.e. it's how you get messages onto the actors mail queue. It's the closest thing that NI-AF has to an actor address in classical Actor Model theory.

Edit to add: I'm sure this discussion has been done to death in the past though!

0 Kudos
Message 23 of 34
(1,940 Views)

DMurrayIRL wrote:

Personally I think it's much better to think of the enqueuer as the actor mail-box

True, but a communication channel, such as the address of a mail-box, can be a reference to the thing receiving the messages.  "DMurrayIRL wrote" it says at top, but "DMurryIRL" is a Username entry in the NI website database; it didn't actually write anything, but it's being used as a reference to the person who did.

0 Kudos
Message 24 of 34
(1,940 Views)

drjdpowell wrote:

DMurrayIRL wrote:

Personally I think it's much better to think of the enqueuer as the actor mail-box

True, but a communication channel, such as the address of a mail-box, can be a reference to the thing receiving the messages.  "DMurrayIRL wrote" it says at top, but "DMurryIRL" is a Username entry in the NI website database; it didn't actually write anything, but it's being used as a reference to the person who did.

Okay, I see that too. My mail-box analogy isn't great anyway, as an enqueuer can be and often is passed around, but a mail-box is a static entity. I have some more thoughts on this, but I don't want to derail the OP's thread, and as I said, I'm sure it's been discussed to death previously as well (I need to look through old threads).

0 Kudos
Message 25 of 34
(1,940 Views)

After much great discussion on AF objects being by-val and what happens

when the object is copied, I think there is still a question asked by

bmitchell that hasn't really been addressed.

The question is "why isn't 'Launch Nested Actor' natively a message, not

only a method, that will send the calling actor a message to launch the

nested actor and thus having the nested EnQr stored in the correct array

for auto stop to work".

If "Launch Nested Actor" were a message, then the VI could only ever be

executed in the Actor Core parent loop message handler. While most of the

time in AF, the design intent is to handle all actions within Actor Core

call parent method, it's not an exclusive case. If it were natively a

message, it would preclude the option of calling it outside of the message

handling system.

Consider the AF project template build into LV. It opens by launching the

root. Looking at Actor Core for the root, you can see that a couple steps

before it gets to the actor core call parent method, it launches two

nested actors. From the in depth discussions above, this is obviously ok

because it happens on the correct instance of the root actor object BEFORE

it's handed off the call parent message handler.

In this example, the 2 new nested actors EnQr's are stored in the correct

place for auto stop to work. However, these 2 EnQr's are also sent off to

the event structure for the root actor to use for it's own purposes (if

you want to call methods of the nested actors, you need to store it's

reference somewhere, not just in the array that handles auto stop). In

this case, the references are stored on the input node to the while loop.

If "Launch Nested Actor" worked as bmitchell suggests, then the nested

actor EnQr's would not be created before the call parent method message

handler was in action, thus precluding a setup like that in the AF

example.

0 Kudos
Message 26 of 34
(1,939 Views)

bmitchell wrote:

I read through your post, but you are still talking about things that aren't relevant. It's also somewhat condescending to make an assumption that I am new to OOP.

They're not irrelevant.  You may not wish to consider them, but they're relevant to the discussion and the information will undoubtedly help other readers (as intended).

It was not my intent to be condescending; I actually made no assumption about how experienced you are with OOP.  You did open this post with the sentence, "I am testing the feasibility of the actor framework", which indicates that you are (likely) new to Actor Framework.

My intent there was actually to send a hint to the team at NI that they perhaps need to add more clarity to their OOP/AF documentation to ensure that new users of AF are clear that the actor data defined by the actor classes is instance data, not class data.

0 Kudos
Message 27 of 34
(1,939 Views)

bmitchell wrote:

See there, the "Launch Nested Actor.vi" gets called on the actor object in the right context, i.e. in the context of the parent Actore Core.vi running the messaging while loop.

Yes; in your code you were calling this VI in the wrong context, i.e., in the context of an Actor Core.vi override's "helper loop".  Using "Send Launch Nested Actor Msg" would be a correct way to achieve your goals in this context.

... In the default way, the Nested Actors property value never gets to this object in the Actore Core.vi loop which is the actual running actor!

Correct.  And everyone commenting on this thread is attempting to get you to see why this is so, and for you to accept that this is the correct behavior.

It never gets to this object in the Actor Core loop of the actual running actor BECAUSE you are invoking the METHOD on a COPY of the actual running actor's object.  Methods execute on objects; you seem to insist that this should somehow result in a message to the actual running actor.  It does not work that way....  Nor should it.

If you want it to result in a message to the actual running actor, you should instead use "Send Launch Nested Actor Msg", as you did in the correct case of your DD structure.  (Why do you think AF needs two different VIs to do the same thing?)

I think you might be helped semantically in grasping the intent of "Launch Nested Actor.vi" if NI had instead named it "Launch and Nest Actor.vi". It results in nesting the launched actor within the actor object of the supplied actor wire.  It's suppose to work that way!

0 Kudos
Message 28 of 34
(1,939 Views)

Here's another way to consider your quandry:

Suppose you had branched the actor wire as you did in your code...  Then you launched the branched actor object as an actor.  This second launched actor now runs as a second independent actor process, along with your original root actor.

Now inside your loop, if things worked the way you envision them, when you run Launch Nested Actor, which of the two root actors that are running would receive the nested actor?

A.  The original root actor

B.  The second running copy of the root actor

C.  Both of them

D.  Neither of them

The correct answer is 😧 Neither of them.  A dead-end object wire receives the nested actor's enqueuer.  And is then garbage-collected.  And that nested actor is no longer controllable.

The most proper place for your code to be launching a nested actor is within a method of the owning actor, NOT within a helper loop in its Actor Core override.  And the way to trigger the method to launch the nested actor is via sending the owning actor a message.

That means either executing "Send Launch Nested Actor Msg" or (better) sending a message to the owning actor for a custom method that runs "Launch Nested Actor.vi".

Launching an actor directly within an Actor Core override helper loop is bad practice.

0 Kudos
Message 29 of 34
(1,939 Views)

A correct answer will directly address why the Launch Nested Actor.vi is setting a property on the actor object in lieu of sending a message.

It would seem that Launch Nested Actor.vi is meant to be used within a launched and runnning actor.  If done here, then setting a property on the actor object is appropriate.

The actor core GUI happens to run in parallel with the actual running actor.  The actor is not running until Call Parent Method is called.  Communication may be sent to the actor from the GUI through messages.  Communication may be sent to the GUI from the actor through some other means such as events or control references.  Anything that is known by both the GUI and the actor must be set before the branch.  For instance, feed in your control references and events into the class private data before branching.

In your sample (as you already know), the GUI has ownership of the nested actor which is not your desired outcome.  I think this just happens to be the wrong place to do this and it is not that obvious.  You really need to envision how this would be done without a GUI first (so build a message for it). Send that message from the GUI to the actor, which will then launch and own the nested actor (where you will likely want to store the nested actor's reference). 

You did find a way to do this through the actor framework in such a way that you used a message and the framework shuts everything down properly.  I think the only problem with this method is that the root actor likely wouldn't know how to interact with the nested actor (other than stoping it) since you are not actively storing the nested actor's reference yourself within the root running actor.

0 Kudos
Message 30 of 34
(1,939 Views)