Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

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

AristosQueue wrote:

D_Hooks wrote:

My vote goes to "Caller's Enqueuer" for the input and "Actor's Enqueuer" for the output of Launch Actor. 

As I said before, this suggestion (minus the apostrophe s) has already been tried in earlier drafts of the AF and was so confusing we changed to the current names.

You're right that this doesn't help with the confusion causing the mistake that Daklu made, but I do think the possesive is important here, and the reason is that programmers have a weird disease which causes them to think that things like "caller enqueuer" or severalWordsWithoutSpaces are a reasonable way of describing things, while normal people (sample size: me) don't think that.

The current text just confuses me every single time, and not in the good way of "let me stop to think how I should do this". It's more of a "wait, what? Actor... to... caller, that means that... xxx" stumbling block. I think the possesive on both the I/O of the launcher and the Read Caller's Enqueuer VI could help.

That said, let me point out that I don't actually have much practical experience with the AF and that I'm still using 2011, so I have "Actor-to-Caller Queue", "Get Queue For Sending To Self" and "To-Self Queue", but I also occasionally open other people's code in 2013 and look at their code.


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

This confusion actually just happened again now when I looked at Daklu's image again even after having this info in my short term memory. I saw "Actor-to-Caller Enqueuer" marked as an input and immediately said "wait, he got that wrong" even though I knew that I looked at it earlier and came to the conclusion that he did label it correctly. I actually had to stop and deconstruct it in my head so that I came out with "this isn't the actor's enqueuer. It's the caller's enqueuer". Maybe it's because it starts with the word "actor" and the output starts with "caller" which causes me to immediately confuse them.

One option would be to change the names to something like "launched actor's enqueuer" or "new actor's enqueuer" for the output (of course, "actor's enqueuer" is basically just a shorthand version of that) and something else for the input? The only thing other than Caller's Enqueuer which immediately comes to mind is "actor's caller's enqueuer" but that is horrible and doesn't solve any of the problems.


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

I also had a brief moment of thinking daklu had mislabeled the input.  But I also see intractable problem of there being two actors involved, each with a "caller".  "New actor's enqueuer" is a great idea for the output, but the only thing I can think of for an input name is "Calling actor's enqueuer".

0 Kudos
Message 33 of 66
(1,578 Views)

I admit to not being able to keep up with the pace of this discussion. As is built into the framework, consider the "Actor-to-Caller Enqueuer" (as defined by the existing Launch Actor.vi), or rather the "Self-To-Caller Enqueuer" field of an Actor's private data, or to be absolutely clear the value returned by "Read Caller Enqueuer.vi", these three names all represent the same data value.

First of all, this inconsistency does us no favors when we are trying to refer to this particular piece of data, as evidenced by some of the most advanced users of LabVIEW still managing to talk themselves in circles. Seriously, active in this discussion are some of the more elite LabVIEW users and designers who are visible to the public and keeping nomenclature straight is still an issue. Please don't take this as a jab at any of you or the framework, it is meant to constructively point out what I believe to be the root of the problem tst originally posted about.

To the topic at hand, consider this "Actor-to-Caller Enqueuer". What is it's function as defined by the framework?

  1. The enqueuer is automatically passed the last ack by the framework when an actor shuts down.
  2. The enqueuer is returned by Read Caller Enqueuer.vi, which is exposed to descendants but not used anywhere in the built in framework.

Since the only exposure a decendant has to this enqueuer is Read Caller Enqueuer.vi, one could argue that the terminal should be called "Caller Enqueuer" since the name would match the context of how that particular bit of data would be used in the context of any actor implementation. I'd buy into that argument.

That said, I prefer to think of what will be signalled when the actor shuts down. Maybe it's another actor, maybe not. Since the context from which the Launch Actor method is called determines where this notification is going to ultimately be sent, the framework doesn't (nor should it) know what that context is. It may not be the actor's "caller". Maybe the context is doing some book keeping and passing some other enquerer in?

Heck, I'd argue that this Read Caller Enqueuer.vi shouldn't even exist as a method, I think conflating the two functions above is an odd choice, although one I understand if the focus of the framework is on a heirarchy. The framework makes no concessions if an actor wants to send messages anywhere else. If an actor makes child actors, the implementation must track those if communication is required. Non-actors? Roll your own as well. Why does a "caller" get special consideration? To be clear, it's a rhetorical question, but the fact that "caller" gets some special concession is interesting to me.

0 Kudos
Message 34 of 66
(1,578 Views)

tl;dr is in boldface.

My idea from yesterday didn't get much traction. So let me try a new one:

Name the terminals on Launch Actor as "Caller's Self Enqueuer" and "Actor's Enqueuer". Rename the VI on Last Ack accordingly. Leave the other VI names unchanged.

kegghead wrote:

Why does a "caller" get special consideration? To be clear, it's a rhetorical question, but the fact that "caller" gets some special concession is interesting to me.

Perhaps rhetorical to you, but the answer bears repeating in light of this discussion: That special consideration is my key observation from tons of user code that made the whole AF work out. Over and over again, I was asked to look at systems that were broken and asked how to fix them or to look at systems that were working and asked how to make them less confusing. I looked at many of them for years. And in every single one, the caller had a special relationship but that relationship was not reflected by the code. And in most, the problem was that the system was fighting against having hierarchy when it clearly had hierarchy (like King Arthur declaring that everyone at the Round Table was equal). And the more I worked on the problem, the more it became clear that the hierarchy deserved special elevation and, indeed, needed to be something that users were heavily guided into while supplying an out for those who were in one of the actually-fairly-rare scenarios where the hierarchy wasn't desirable.

kegghead highlighted a new issue with any terminal name change.

Changing the terminal names is vialbe. Changing the VI names is not. The VI names would be a breaking change and it would keep a new version of the framework from being published outside the normal cadence of LabVIEW itself to have a change that requires mutation. Not to mention I'd never get time or permission to make that change to 2014 at this late date.

The VIs are:

  • Actor:Read Caller Enqueuer.vi
  • Actor:Read Self Enqueuer.vi
  • Last Ack: Read Caller-To-Actor.vi  [I forgot about this one until kegghead mentioned it.]

If we change the name on the Launch Actor terminal, we would need to do something about "Read Caller-To-Actor." I would probably leave the existing VI, mark it as deprecated, and add a second VI with the new name that did exactly the same thing. If we have to change the names "caller enqueuer" and "self enqueuer", then similar deprecate/replace would be applied to those VIs.

0 Kudos
Message 35 of 66
(1,578 Views)

AristosQueue wrote:


So let me try a new one:

Name the terminals on Launch Actor as "Caller's Self Enqueuer" and "Actor's Enqueuer". Rename the VI on Last Ack accordingly. Leave the other VI names unchanged.

The "self" seems weird here. Self is relative and isn't really relevant here. I think it's preferable to the current situation, but I still think it would confuse some people.

I'm not sure you're going to like this, and I don't think that it has been suggested before, but how about splitting the launch VIs into three VIs:

  1. Launch actor (actor, caller's enqueuer) - exists.
  2. Launch top level (actor) - already discussed in the other thread.
  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).

The main reasons I don't like it is that it adds yet another way of launching an actor (although ideally 2 and 3 will be used almost exclusively) and that the VI now has two actor inputs, which can cause users to wire them incorrectly (although that could return an error if the caller doesn't have a valid enqueuer). If this is done, maybe they should be put into a poly VI.

Actually, thinking about this some more, let's get rid of #1 entirely. If the caller is a special case which is built into the framework, then the framework should handle it automatically (#3) or not at all (#2). That will solve everything here, because there won't be names and confusions. Any other enqueuer that you want to pass to an actor is a special case and should be part of the actor's special code.

Edit - we could also combine #2 and #3 into a single VI by making the caller's input optional and then we're left with a single launch VI, but that brings us back to the discussion in the other thread.


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

An actor has access to three categories of enqueuers: self, caller, and called. I think the terminology is fine. What's missing are some nice, clean, simple examples of reusable actors. Cooler demo does a lot, but I didn't learn very much until I made a few of my own small, simple actors.

0 Kudos
Message 37 of 66
(1,578 Views)

Thinking about it a little further, "Caller's Self Enqueuer" isn't a bad option.  If the 1:1 name matchup of a "Caller Enqueuer" input and "Read Caller Enqueuer.vi" trips people up (including the ninjas posting here) then making the input name a little wordy for the sake of clarity seems like a reasonable decision.  It fits well within the bounds of the current VI names, and I defintiely like it a lot more than the Caller-to-Actor and Actor-to-Caller terminology being used now (which actor and which caller again?).

It strikes me as slightly inelegant that each actor has one enqueuer, and that enqueuer is referred to as its "self enqueuer", but I already talked myself into "Read Self Enqueuer.vi" having an appropriate name. 🙂

0 Kudos
Message 38 of 66
(1,578 Views)

    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.

    a) If you are trying to launch a nested actor from within one of the parallel while loops on Actor Core, you don't have the actor object any more (unless you forked the actor wire which you should NEVER do).

    b) If the caller is not itself already launched, that's a runtime error. By requiring the input to take an enqueuer instead of a raw actor object, we do a better job of ruling out the attempt to launch a nested actor from a not-yet-launched caller.

    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).

    0 Kudos
    Message 39 of 66
    (1,578 Views)

    AristosQueue wrote:

    Are you proposing passing the caller object itself into the function?

    Yes. That would make the whole thing simpler because you never have to pass the caller's enqueuer yourself.

    a) If you are trying to launch a nested actor from within one of the parallel while loops on Actor Core, you don't have the actor object any more (unless you forked the actor wire which you should NEVER do). 

    I don't think you actually need the updated actor, since the caller's enqueuer is static and was set when the actor was launched. Any branch of the actor wire inside the core should have the correct enqueuer on it (I'm assuming. I can't actually look at the code and I don't remember exactly where it's created).

    Anyway, I don't think that this is significantly different from the current situation. Today, users can still branch wires you don't want them to branch and they can still do stupid things. If needed, you could tell people "the right way to do this is for the actor to send a message to itself to launch the nested actor". True, it's preferable if this was enforced, but my understanding is that this isn't even enforced today.

    b) If the caller is not itself already launched, that's a runtime error. By requiring the input to take an enqueuer instead of a raw actor object, we do a better job of ruling out the attempt to launch a nested actor from a not-yet-launched caller.

    You're correct that there would be a runtime error, but I'm not at all sure that the current situation or the other proposed options don't leave just as much room for errors. Today, you're requiring people to understand exactly what the caller's enqueuer is, how to generate it and correctly pass it on. In this proposed situation, you're just telling them "understand that this actor launches that actor and that it's going to be its parent. If you want to talk to the parent from the nested, use the Read Caller's Enqueuer VI. You don't need to care how that enqueuer was created. It just is".

    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).

    Umm, you wouldn't? Wasn't that the whole point of the other thread about top level actors? If you mean to say that you do want the actor to send messages *somewhere* then that's a special case and you tell the user "write your own code for that. Get an enqueuer from the actor you want to receive the messages and send it to the new actor".

    I really do think that if this can work, then it has the potential to significantly simplify the entire issue and it seems to me to be conceptually correct - if the caller's enqueuer is an integral part of the framework, the framework should handle it, not the user. It's a special enqueuer and the user should have as little control over it as possible.


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