09-18-2019 08:36 AM
Hi All
Could someone explain me how to launch an actor X for every time an event Y occurs? Taking the LV actor framework template as an example:
Each time an event (could be the user clicking a button on the front panel of the root actor) occurs, I would like to launch an actor X. That is, I would like to launch the actor form inside the event loop (marked A on the screenshot below). Clicking the button N times, would then give me N copies of the X-actor running. I found some inspiration in this thread, but it does not seem to solve my issue
If I understand how the actor framework works, the problem is that each nested actor needs to have a queue on the root actor's private data cluster control (see 2nd picture below). But how can I put N queues in the private data cluster?
Second problem is that the nested actor's enqueuer needs to be fed into the data cluster of the root actor (see encircled code in the first picture below). As demonstrated in the example, which I linked to above, this can be solved by having a method of the root actor launching the nested actor. The method would launch the actor and wire its' enqueuer into its' own data cluster. However it still requires that the root actor's private data cluster control contains a queue for the X-actor.
I hope my description makes sense. If someone could give an example that would be fantastic!
Solved! Go to Solution.
09-18-2019 08:42 AM
09-18-2019 08:50 AM
Do you want the nested actor queues accessible within the actor core (where messages are handled)? If so I've always done things like this by sending a message to myself from the helper loop and doing the action in the message handler. This way I have access to the actor data (the copy that actually gets used during message handling). In your case just send a message to yourself every time an event is hit. This adds some plumbing work, but gets the job done. It's also why I try to avoid using helper loops as much as possible (why not create another actor?). Looks like you have one to handle the UI which is one of the cases where I don't think you can avoid it though.
To have N queues in the private data I'd use an array of queues. If you need some other way of accessing the queue other than index, then you could use a map (native in LV2019 and you can use variant attributes otherwise).
09-18-2019 10:18 AM
To have a dynamic number of Actors you certainly need to use something like an array of Enqueuers. A Map is another option, and as mbremer points out allows you to use a non-integer key (or a non-consecutive integer, etc) as the lookup "key". Which is preferably depends on how you want to access the specific enqueuer when you wish to send the callee a message.
You will probably need to use a message, as Sam highlighted, because otherwise you cannot affect the contents of the caller's private data in a particularly useful way (you can make a copy by forking the wire, but this copy won't be the Actor that's running - it will be essentially just a normal object that you could keep in a shift register).
If you don't need to send messages from messages then it should be possible to avoid the "Launch Other Actor Msg" by storing the enqueuers in a shift register in your Actor Core (either as an array or Map). This won't allow you to message them from anywhere except that loop though (and if you come up with complicated workarounds like storing the array in a notifier then you'd really be much better sticking within the framework and storing them in the Actor's private data (caller actor)). So do this only if you're confident you'll never want to message them from outside of your Event loop (i.e. really, don't do this...)
09-18-2019 11:03 AM
Here You can see a small example. Run the launcher.vi.
09-18-2019 03:26 PM
@cbutcher wrote:
If you don't need to send messages from messages then it should be possible to avoid the "Launch Other Actor Msg" by storing the enqueuers in a shift register in your Actor Core (either as an array or Map). This won't allow you to message them from anywhere except that loop though (and if you come up with complicated workarounds like storing the array in a notifier then you'd really be much better sticking within the framework and storing them in the Actor's private data (caller actor)). So do this only if you're confident you'll never want to message them from outside of your Event loop (i.e. really, don't do this...)
While what Christian describes here is technically possible, do future you a favor and follow Christian's advice and don't do this. In general don't store state in the helper loop unless you absolutely have to.
09-18-2019 03:39 PM
You could also use an Action Engine to store the Enqueuers, though I think the best way is to just send yourself a message. (I'm not a huge fan of AE's as they can be kind of hard to debug, but they certainly have their uses)
09-19-2019 09:24 AM
Thanks a lot to all of you for your replies. They have all been helpful. Let me answer some of your questions:
I would like to have access to the enqueuers of the nested actors in the root actor's core. It is possible that I could write my program without, but that would require a complete restructuring, so I would have to think more about that.
p4keal, thanks for your example, but it seems like the enqueuers of the nested actors are not available in the root actor's core, so it is doesn't solve all my problems. It is still useful though!
Storing the N enqueuers in an array seems appealing to me. I have tried to combine this with the "launch nested actor by method" approach like in p4keal's example, and results seem promising so far! I will get back, if I have further questions. Thanks again
09-19-2019 10:29 AM
If You need enquers of nested actor - just define an array of enquers in your root's data cluster. Or use a variant to store them.
Here is v2 of example. Start and close some nested actors and watch root ui. You can only access root's data from an action vi. If you want to send a message to a nested actor -> define a action vi and a message around it. For the second step You can use wizzard. You can get enquer from the variant by actor's name with "get variant attribute.vi"