Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Integrating AF & LVOOP with hardware

Solved!
Go to solution

It takes a while. It's a shift in the way you think. Kind of like when you first learn OOP. After a few projects, things will start going smoother and make more sense.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 21 of 88
(2,337 Views)

@Taggart wrote:

It takes a while. It's a shift in the way you think. Kind of like when you first learn OOP. After a few projects, things will start going smoother and make more sense.


As I was jotting down some notes about this discussion, I realized that I'm not aware of how to accomplish one messaging task AF. I get how interfaces define the structure of a message, but I was originally wondering if they also enabled communication between arbitrary pairs of nested actors. Seems that such arbitrary communication is not possible without sharing the enqueuer's reference explicitly, which is certainly not "easy" (and might even be bad practice as it introduces coupling between actors where there shouldn't be any?) 

 

Let's say nth nested actor generates a message meant for mth nested actor. nth and mth are not right above/below each other. Question: is the appropriate practice then for nth to share messages "up" its ancestor lineage until it reaches a common ancestor with actor mth, and then that common ancestor delegates the message down to mth? Not sure if my question is phrased well enough. 

 

(For an explicit example, if my power meter actor generates a message intended to my spectrum actor -- like hey I detected power please take a spectra -- I suppose power meter should tell my main program's actor that message, and then the main program's actor delegates it to OSA. Doesn't seem to make sense to have power meter actor talk to OSA actor directly because in one particular program it was needed.)

 

 


------------------------------------------------------------------------------------

Please join the conversation to keep LabVIEW relevant for future engineers. Price hikes plus SaaS model has many current engineers seriously concerned...

Read the Conversation Here, LabVIEW-subscription-model-for-2022
0 Kudos
Message 22 of 88
(2,333 Views)
Solution
Accepted by WavePacket

Bingo. 99.9% of the time it's best to handle communications only with callers and callees. Sibling actors shouldn't communicate with each other*. This helps massively reduce coupling and actually helps debug as you can see all of the messages.

 

In your example, reconsider your messages. A general purpose power meter actor might need to have an "alert" function, but it definitely doesn't need a "take a spectrum" function. You will have one top level actor that's launched both of those that will "translate" one message into the other. For this application, your business logic is:

Power detected -> Take spectra

 

Another application might be:

Power detected -> Send email to Jerry

 

If you separate all of that, and only send messages up and down the tree, you can have far more general purpose actors. In your case, let's call your business logic actor "Top Actor". You set your Power Meter actor to send a message notifying when it sees power up to Top Actor, then when that message comes in Top Actor sends a message to Spectrum Actor that says "Take a spectrum". Alternatively, if your spectrum analyzer doesn't require its own loop, it can simply be an object within Top Actor. When Top Actor receives the Power Detected message, it just asks the Spectrum Analyzer what the current spectrum is.

 

You will initially think "But wait, this means there are two messages here when I really only want to do one thing", and yes that's true. However, if you ever want "Power detected" to mean something else, or if you ever want to use the Power monitor actor in another project that doesn't have a Spectrum actor, you have to separate the functionality out.

 

*: I feel like I remember a really, really specific use case where someone had a good reason to do sibling actor messaging and not go through the chain. I believe it involved some very high data rate pipelining stages; it was not a generic actor use case. I personally have continually sent 2 MS/s data streams through two separate actors and didn't see any issues with RAM usage.

0 Kudos
Message 23 of 88
(2,326 Views)
Solution
Accepted by WavePacket

> , but I was originally wondering if they also enabled

> communication between arbitrary pairs of nested actors

 

No. And if interfaces did enable it, we would need to figure out how and put a stop to it! 🙂

 

It would be very bad if the introduction of interfaces allowed arbitrary short circuiting of the actor tree. Luckily, cutting across the tree still requires conscious sharing of the Enqueuer by the caller actor, and it is still something of a hurdle to accomplish. 

 

> (and might even be bad practice

 

Might be? I thought every AF document published included admonitions against doing that unless as a last resort you're absolutely backed into a performance corner. I guess not. 🙂

 

Yes, it's bad practice. The more you increase arbitrary routing of messages, the greater the chances of deadlocks, echo chambers, and undefined state transitions. You increasingly lose the ability to do replay debugging. You increasingly lose the ability to do isolation testing.

 

> is the appropriate practice then for nth to share messages "up" its ancestor

> lineage until it reaches a common ancestor with actor mth, and then that common

> ancestor delegates the message down to mth? Not sure if my question is phrased

> well enough.

 

YES. 🙂 Yes, that is appropriate practice. Yes, your question was phrased well enough. 🙂

 

> Let's say nth nested actor generates a message meant for mth nested actor. 

 

How does the Nth actor even know that the Mth actor exists? Why does it know? In my idealized system, Nth and Mth actors would be coded by different developers who didn't know each other and had no clue their code would ever be used together. It is only the caller actor that knows about N and M, and it is for the caller actor to route messages as necessary with -- and this is the key part -- domain translation as needed. The temperature sensor shouldn't know that 400 degrees is the temperature when the turkey needs to go into the oven... it should not be sending "Put Turkey In Oven" to the turkey-mover robot. It just says, "Temperature is 400 deg." The kitchen AI, which manages both the temp sensor and the turkey-mover robot, gets the temp and knows to send the "Put Turkey In Oven" message. It translates information from the sensor domain to the robot domain.

 

What interfaces do let you do is have the same message type be reused throughout the system when a given domain crosses many actors. Each actor that receives the message may (will) have a different response to the message, and a receiver may turn around and send the same message to the next layer (up or down) of actors(s), but that is the actor's choice to do so, not something inherent in the message. At no point does some other actor get to override the reciever's choice about whether or who to message next. That is the heart of the Actor Framework's major break with previous messaging systems, and it is the key fact that makes the AF more stable as systems scale larger than its predecessors.

Message 24 of 88
(2,323 Views)

> Power detected -> Send email to Jerry

 

I liked my Turkey-Moving Robot example better. Every kitchen should have individual robots each dedicated to carrying one specific item, right? 🙂

0 Kudos
Message 25 of 88
(2,311 Views)

I've got another "message" that I'd like to send all of the "actors" 🤣 in this thread.

 

I was poking around the new project -> actor framework example that ships with LabVIEW. I've attached images of its root actor core so it's clear which one I'm speaking of.

 

I was surprised, perhaps wrongly, to find a potential coupling between the nested actors. "Task.VI' (highlighted) within alpha nested actor actually uses as a subVI "Send Log Event.VI" (also highlighted). A nested actor seems to know about its calling actor then, right?

 

Is that an example of an interface would be useful? If both alpha and its calling actor inherited from the same interface, then alpha actor could send calling actor a message without knowing anything explicit about is calling actor.


------------------------------------------------------------------------------------

Please join the conversation to keep LabVIEW relevant for future engineers. Price hikes plus SaaS model has many current engineers seriously concerned...

Read the Conversation Here, LabVIEW-subscription-model-for-2022
Download All
0 Kudos
Message 26 of 88
(2,307 Views)

@AristosQueue (NI) wrote:

The temperature sensor shouldn't know that 400 degrees is the temperature when the turkey needs to go into the oven... it should not be sending "Put Turkey In Oven" to the turkey-mover robot. It just says, "Temperature is 400 deg." The kitchen AI, which manages both the temp sensor and the turkey-mover robot, gets the temp and knows to send the "Put Turkey In Oven" message. It translates information from the sensor domain to the robot domain

 

Hi AristosQueue,

 

This is the ESSENTIALS I wish I knew when I started poking with AF and it is very good articulated here. I learned it in a hard way. If you just start naming your methods like "Something happened" instead of "Do something" your actors become so cute and easy to use 🙂

Nikita Prorekhin
CLA
Message 27 of 88
(2,288 Views)

@WavePacket wrote:

I was surprised, perhaps wrongly, to find a potential coupling between the nested actors. "Task.VI' (highlighted) within alpha nested actor actually uses as a subVI "Send Log Event.VI" (also highlighted). A nested actor seems to know about its calling actor then, right?


I don't mind coupling between actors intended to be used together in projects that have little need for code reuse and where testing can be done on the business logic of the actors without worrying about the somewhat trivial messaging logic. So if it is "caller sends request, nested computes, nested sends response", as long as "nested computes" can be tested independently (because it's a function I can just call as part of my tests), the tight binding to me is just fine. This test philosophy does not sit well with others. As a project gets larger and develops more middle-layer actors, the ability to do such tight bindings grows rarer.

0 Kudos
Message 28 of 88
(2,274 Views)

@AristosQueue (NI) wrote:

@WavePacket wrote:

I was surprised, perhaps wrongly, to find a potential coupling between the nested actors. ...


I don't mind coupling between actors intended to be used together in projects that have little need for code reuse and where testing can be done on the business logic of the actors without worrying about the somewhat trivial messaging logic. ...


Fair enough for when reuse is not foreseen. 

 

In the other case where reuse is foreseen, does it make sense to use interfaces then to define the messages? Reuse is desired in my case, as I have many software projects -- each with different business logic actors -- where all these business actors will hopefully each reuse the same optical spectrum analyzer actor and power meter actor. Seems like I want the nested hardware actors fully uncoupled from the business logic actors.

 

If I define the interface messages, all the nested hardware actors can inherit the interface, and the business logic actor can inherit the just the interfaces appropriate to its needs. This way, my nested hardware actors will only couple to a reusable interface and not too any particular non-reusable business logic.

 

Am I "inheriting" (🤓!) the correct understanding here?


------------------------------------------------------------------------------------

Please join the conversation to keep LabVIEW relevant for future engineers. Price hikes plus SaaS model has many current engineers seriously concerned...

Read the Conversation Here, LabVIEW-subscription-model-for-2022
0 Kudos
Message 29 of 88
(2,272 Views)

@WavePacket wrote:
In the other case where reuse is foreseen, does it make sense to use interfaces then to define the messages?

Yes. In fact, Allen is strongly considering the position that all nested actors should talk only to interfaces, never directly to callers, on the grounds that the weight of creating the interfaces is minimal and then ne doesn't have to think about whether reuse is a possibility or not. I think that's going too far, especially for smaller AF projects. We have not had interfaces in LabVIEW long enough to make a preferred policy, but it's the hypothesis ne is playing with these days.

0 Kudos
Message 30 of 88
(2,263 Views)