Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Request: lose the "Caller-To-Actor" and "Actor-To-Caller" language

Oh, and you know what? This scheme has a great benefit - enqueuers are now created in one place and one place alone - the Launch Actor VI. Launching an actor creates its enqueuer and returns it and that's it - each actor has its enqueuer and there are no enqueuers dangling in mid-air. That will simplify the system and remove some VIs from the palettes (msg Q pair, etc. Those are all now private).


___________________
Try to take over the world!
Message 41 of 66
(1,436 Views)

I like tst's idea... In fact I was just about to suggest the same thing

But I'd take it a little further:

  1. Rename Launch Actor to "Launch Sub-Actor" and deprecate the original.
  2. Stop thinking about launching as "something that happens to every actor (sub-actor)", and start thinking about it as "something every actor (caller) can do".
  3. Reorganise the conn pane so that it has a standard object-in terminal at the top left. This is consistent with the vast majority of class methods. The object-in is obviously the "caller"... but there's no need to use that word here.
  4. Make the 2nd input terminal the "Sub-actor" input. The sub-actor is just a normal (required) input of the launch method.
  5. Make the 2nd output terminal the "Sub-actor's Enqueuer" output.
  6. Reserve the "caller" terminology for use exclusively inside an actor. As tst said, this removes the confusion at its root.

And of course we still add a "Launch Top-level Actor" method for completeness.

0 Kudos
Message 42 of 66
(1,436 Views)

AristosQueue wrote:

    3. Launch from actor (actor, caller actor) - new, and gets the caller's enqueuer on its own. If most people use this, it will solve the confusion because you don't wire in the enqueuer and then I think it matters a lot less what we name the input on #1 (I would probably say it shouldn't have the term "caller" any more).

    How would it "get the caller's enqueuer on its own"? Are you proposing passing the caller object itself into the function? That's not going to work for three reasons.

    ...

    c) How would you handle getting messages from an actor when the caller isn't an actor? That's a pretty significant use case (it gets lots of press in these forums).

    I initially thought (c) was a problem, but I think that any use from a non-AF actor is going to require some kind of adapter code, and that code can be an AF actor.  Any call from a non-actor code (like a synchronous API for interacting with the actor) can't really use the "Actor-to-caller" queue, and thus must either also use an adaptor actor, or use something like reply messages.

    0 Kudos
    Message 43 of 66
    (1,436 Views)

    I made a quick mockup to help see if there are obvious hidden issues here. I think that this shows quite nicely how this would simply circumvent all the problems people were having here. Here are the two new VIs:

    Actors.png

    The names and setup are obviously open to changes, but this simplifies the entire system into a couple of simple rules:

    1. When an actor is launched it creats an enqueuer so that it can be talked to.
    2. If A launches B as a nested actor, then B has implicit access to A's enqueuer as its caller.

    I think this simplification is valuable enough that it's worth delving into to see whether it can actually be done, what all the problems with it are, whether they can be addressed, are they preferable to the problems with the existing system, can the various use cases be handled, etc.

    Also, note that the existing actor in the second image isn't modified at all by the launch nested actor VI, so technically it doesn't have to come out of it (and there are good arguments for not having it as an output. In fact, I think I would prefer not having it).


    ___________________
    Try to take over the world!
    0 Kudos
    Message 44 of 66
    (1,436 Views)

    And a before and after of Daklu's code, which is now a lot simpler:

    Nested Actor.png


    ___________________
    Try to take over the world!
    Message 45 of 66
    (1,436 Views)

    I like the direction this goes, so I did some playing.

    The one sticking point seemed to me to be launching a subactor from one of the appended loops in Actor Core. I *really* don't want to get people thinking that it is ever ok to split the Actor object wire to a separate loop. We have seen too many people on these forums totally confused by that -- they think that both objects will stay up-to-date with state changes.

    So I'd suggest adding one more standard piece:

              Launch Nested Actor Message.lvclass

    This message's payload is an actor, and it tells the actor to launch a nested actor. If we make it a standard message on Actor, we could go ahead and add another feature that has sometimes been discussed -- making the array of nested actor enqueuers a part of Actor and automatically handling stopping those nested actors in Stop Core.vi.

    Thus if I wanted to launch a nested actor from one of the secondary loops, I wouldn't launch it directly. I'd post this message to launch it.

    Yes?

    Message 46 of 66
    (1,436 Views)

    I agree Yair and fabric's changes seem to simplify things; however, I wouldn't eliminate the Launch Actor (actor, caller's enqueuer) as suggested.  Seems to me it's still necessary for integrating AF code with non-AF code.  Maybe put it in the advanced palette, but don't eliminate it completely.

    The one sticking point seemed to me to be launching a subactor from one of the appended loops in Actor Core.

    What's the use case for launching a sub actor from a helper loop?  Launching sub actors from a loop other than the message handling loop (Actor Core) seems like a dangerous move for newbies anyway, since it opens the door to inserting a helper loop in an actor and sub actor's communication path, which leads to other tricky problems such as distributing an actor's state data across multiple loops.  (It can be done successfully in the current design as long as the launching actor's enqueuer is used as the "actor-to-caller" input instead of the enqueuer for a helper loop, but newbies can easily miss the importance of such subtleties.)

    The only reason I can think of why one would want to launch a sub actor from a helper loop is because the launching process takes too long and will interrupt the flow of messages too much.  This seems like a rather advanced scenario and can be still be resolved by feeding the launching actor's enqueuer to the helper loop and using Launch Actor, or by understanding that it is okay to branch the Actor wire if all you are doing is feeding it into Launch Subactor in the helper loop.  Neither solution is particularly newbie friendly, but it does seem like a fairly uncommon requirement.

    (As an aside, if splitting the actor wire is undesireable, I'd suggest putting Actor output terminals on the Get Enqueuer methods.)

    ---------

    [Edit - I attached the 2 actor sample code (in LV2012) I wrote to understand the issues being discussed in this thread.  Maybe it will provide a common reference point for discussion... or maybe it will only be good for comic relief. *shrug*]

    0 Kudos
    Message 47 of 66
    (1,436 Views)
    If we make it a standard message on Actor, we could go ahead and add another feature that has sometimes been discussed -- making the array of nested actor enqueuers a part of Actor and automatically handling stopping those nested actors in Stop Core.vi.

    I think this is probably a good idea.  The current design is asymmetrical--stops propagate up the tree (at least when caused by errors) but not down.  I had thought this behavior was already built into the framework and couldn't figure out why my sample code wasn't halting correctly.

    0 Kudos
    Message 48 of 66
    (1,436 Views)

    Daklu wrote:

    What's the use case for launching a sub actor from a helper loop?  Launching sub actors from a loop other than the message handling loop (Actor Core) seems like a dangerous move for newbies anyway, since it opens the door to inserting a helper loop in an actor and sub actor's communication path, which leads to other tricky problems such as distributing an actor's state data across multiple loops.

    Huh? No idea what you're talking about here.

    Daklu wrote:

    (As an aside, if splitting the actor wire is undesireable, I'd suggest putting Actor output terminals on the Get Enqueuer methods.)

    Splitting it to another ongoing loop that maintains state (or, worse, gives the impression that it maintains state) is the problem. Forking it to read-only methods is more than fine.

    0 Kudos
    Message 49 of 66
    (1,436 Views)

    Daklu wrote:

    I think this is probably a good idea.  The current design is asymmetrical--stops propagate up the tree (at least when caused by errors) but not down.  I had thought this behavior was already built into the framework and couldn't figure out why my sample code wasn't halting correctly.

    Ah. Thank you for reminding me why we don't do this already.

    Stops do propagate up the tree automatically, but that behavior is overrideable in the handling of Last Ack. Stops going down the tree automatically is the problem -- where does the override go? Stop Core is a Must Call Parent, and for good reason -- destructors need to propagate up. But actors have multiple use cases where they want to quit but leave their nested actors running.

    This came up a while ago (can't find the thread now) and the conversation petered out without action. But my memory is that we couldn't find a good way for an actor to designate which nested actors should stay running and still leave the general shutdown mechanism in the parent's hands.

    Maybe that's an input on the Launch Nested Actor.vi? A boolean input for "Nested actor stops when this actor stops? (T)" , perhaps? Except it seems like something that a programmer might want to decide at shutdown instead of at launch.

    0 Kudos
    Message 50 of 66
    (1,436 Views)