09-10-2018 12:03 PM
Basically the Caller, receives the message from it's nested actor (so that would typically be a concrete child of an abstract message) and then when the caller receives it, the Do.vi for that message simply sends a concrete message to the other nested actor.
So the downside to the normal strict hierarchical, is that you end up with a bunch of messages that do nothing but forward messages along the chain (of course you are not technically forwarding the messaging object but sending a new message which has the same intent).
So yes as in the last line your post you do end up with a lot of "forward this information to actor B messages"
09-10-2018 12:09 PM
For the logger application, I would create a parent actor that owns an enqueuer for the logger in its private data and make all your actors that need to log data inherit from that. Then you can write one method in your parent class called "log string" that takes a string and sends it to the logger.
Then you have to launch the logger first so you can get its enqueuer and everytime you launch a nested actor, you give it the enqueuer to the logger. Then each of those nested actors can call the "log string method".
The parent class can protect the logger enqueuer so that other loops can't accidentally shut it down or anything or send it some other message.
09-10-2018 01:50 PM
@CanadaGuy wrote:
I see...I have been paying little to no attention to the purpose of a message (data or control), so it appears I need to start distinguishing between the two.
Only if you break hierarchical messaging. 🙂 And truthfully, when I say control messages should always follow the tree, I mean it in the same way as when I say all messages should follow the tree. It's safer, but under certain circumstances it might be okay to violate that rule.
(Hint: Not wanting to create the forwarding messages isn't a valid reason to use direct messaging.)
Is there an example showing perhaps 2-3 nested levels of actors where the messaging is passed up and down the tree? I don't think I've seen one yet, and if I did, I didn't recognize it.
I don't use the AF, so I don't have one. I'd be surprised if there isn't one out there.
09-10-2018 02:12 PM
When they release the videos from GDevCon you should check out Dr. Powell's presentation on messaging. It doesn't have the AF example you are looking for, but it does have a lot of really useful information and theory about messaging paradigms including peer networks versus a tree structure. It talks about the pitfalls of breaking the tree hierarchy. Generally, I only break it as a last result and with good reason.
09-13-2018 03:21 AM - edited 09-13-2018 04:47 AM
@CanadaGuy wrote:
I have a root actor that launches two nested actors (side by side in parallel, not cascaded). The root actor is a UI actor. The first nested actor is a logging actor, the second actor is a simulation actor. For messages from each callee to the caller actor, I'm using the abstract/child message approach so the nested actors are not dependent on the root actor.
How do I send a log message from the simulation actor to the logging actor? One method I thought would be to includes a user event in the root actor that will fire when a log message is received from the simulation actor, and forward it to the logging actor. The other thought I had was that I could initialize the logging actor first, get its enqueuer, then initialize the simulation actor with the logging enqueuer in place. Does this create some dependencies that I'm not aware of?
I would like to suggest an idea:
To avoid generating of may be unnecessary forwarding messages,
You can override the Receive Message.vi in Root Actor. You must also define a base class for all logger messages, e.g. Msg for Logger.lvclass inheriting from Message.lvclass. For the logger messages You have to change the parent class from Message.lvclass to Msg for Logger.lvclass.
In Receive Message.vi You can verify that the message is derived from Msg for Logger.lvclass and forward the message to Logger Actor. Otherwise, the parent Receive Message.vi is called and the root proceed the message by itself. I attach a sample project (LV2014). Run the Launcher.vi
08-17-2021 09:17 AM
@p4keal wrote:
@CanadaGuy wrote:
...
I would like to suggest an idea:
To avoid generating of may be unnecessary forwarding messages,
You can override the Receive Message.vi in Root Actor. You must also define a base class for all logger messages, e.g. Msg for Logger.lvclass inheriting from Message.lvclass. For the logger messages You have to change the parent class from Message.lvclass to Msg for Logger.lvclass.
In Receive Message.vi You can verify that the message is derived from Msg for Logger.lvclass and forward the message to Logger Actor. Otherwise, the parent Receive Message.vi is called and the root proceed the message by itself. I attach a sample project (LV2014). Run the Launcher.vi
Thanks for posting this, I enjoyed learning about modifying the default behavior of Receive Message.vi, which I hadn't thought about before.
In 2020 now, I'm trying to understand if this problem (i.e. "avoid generating of may be unnecessary forwarding messages") is still relevant. If I use an interface "log message" implemented by root, log, and all N nested actors which can generate a log event, then I need N+2 implementations of the log message interface. Is that N+2 implementations the problem of unnecessary forwarding messages?
In your implementation, you have override the Receive Message.vi in Root Actor, create a new Logger.lvclass inheriting from Message.lvclass, and then put that send log entry class within the private data of N nested actors which can generate a log event.
These methods (LabVIEW 2020 interface) and your method seem comparable in amount of code-burden, right?
08-17-2021 09:27 AM
@Taggart wrote:
For the logger application, I would create a parent actor that owns an enqueuer for the logger in its private data and make all your actors that need to log data inherit from that. Then you can write one method in your parent class called "log string" that takes a string and sends it to the logger.
Then you have to launch the logger first so you can get its enqueuer and everytime you launch a nested actor, you give it the enqueuer to the logger. Then each of those nested actors can call the "log string method".
The parent class can protect the logger enqueuer so that other loops can't accidentally shut it down or anything or send it some other message.
I'm also trying to understand the relevancy of this (valid) solution now that we have the 2020 version.
So if I instead use a interface "log message" inherited by root, log, and all N nested actors which can generate a log event, then all my N actors can fire off send log event messages to root. In roots implementation of the interface, it forwards it off to logger actor.
Does that capture all of the benefit of your solution & reduce coupling (b/c the nested actors don't inherit from root) but not zero coupling (as the nested actors do all inherit from the interface).
01-22-2024 09:08 AM
Would you provide me an example of it for learning AF?
01-23-2024 01:08 AM - edited 01-23-2024 01:11 AM
You have several options as described in this thread. If you want to learn overwrite message receive approach, example is available three posts above:
https://forums.ni.com/t5/Actor-Framework-Discussions/Communicate-Between-Parallel-Nested-Actors/m-p/...
If you want to use the abstract message method as specified in solution: I would suggest using interfaces instead of abstract messages.
Update:
to learn about interfaces in LV see here: https://youtu.be/1lFMZe9SwMY?si=zrOYHMMFdaeDS2id