Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

How to avoid data dependencies between Actors

Thoric schrieb:

Some of the discussion makes my head spin. I followed Jon McBee's link and got lost about three quarters of the way down the blog. "Creating abstract children of AF message class to ensure zero-coupling between actors" sounds like a complex approach that I don't fully get, mainly because I think I'm still about one chapter behind my Computer Science textbook than some of the brainboxes on here.

Speaking of me, I don't really have Computer Science background, that's why I try to find analogies of complex context like that into real-life. It usually works though I have to admit that I usually don't know the proper names in terms of CS and it takes time. But eventually there is this Heureka moment

Thoric schrieb:

So currently I'm still a bit overwhelmed by the AF. It's clearly very clever in its design and abilities, but my attempts to implement it result in my spending much more time trying to understand how I should be correctly implementing my solution, leaving no time to actually create working code. I feel like it actually gets in the way, rather than help me. Perhaps I just need more education on recommended ways to use it.

I can definitely understand that one gets overwhelmed. That's why IMHO one should really start with really simple applications to get a grip on the framework.

Guess we'll meet at the CLAE in Aprol. If you like and we can find a bit of spare time, I will be happy to show you some of my code and explain some aspects of the implementation I have chosen.

Message 21 of 36
(2,180 Views)

Oli_Wachno wrote:

...that's why I try to find analogies of complex context like that into real-life.

So do I, but as pointed out by James Powell my analogies tend to be too complex. It's hard to create a workable analogy between the software domain and real-life

Oli_Wachno wrote:

I can definitely understand that one gets overwhelmed. That's why IMHO one should really start with really simple applications to get a grip on the framework.

Guess we'll meet at the CLAE in Aprol. If you like and we can find a bit of spare time, I will be happy to show you some of my code and explain some aspects of the implementation I have chosen.

That would be great, thanks, I'd appreciate it. Perhaps we could earmark one of the mid-morning session breaks and find a table.

Thoric (CLA, CLED, CTD and LabVIEW Champion)


0 Kudos
Message 22 of 36
(2,180 Views)

Oli_Wachno wrote:


1.) Hierarchy: how should the Actors communicate? Use a strict heirarchy or every Actor talking to one another. I have to admit, that I am in general in favour of a strictly hierarchical approach (yes, the Boss organising the pencil! Those highly paid managers need to be occupied so they don't get bored and take strange decisions ). It involves quite a bit of message handling, but it also makes debugging easier. Imagine a room full of people talking to each other and you have to find out, what's going wrong...

There is an alternative to both strict heirarchy and every Actor talking to one another, where Callers can "connect" their subActors, allowing communication directly between them, subject to limits set by the Caller.  This is sort of like a lot of small rooms, with one person in each room moderating the conversation.

0 Kudos
Message 23 of 36
(2,180 Views)

To follow on to what drjdpowell said above, take a  look at the mediator pattern.  It is another alternative to both a strict hierarchy and every actor talking to one another.  In this case it isn't the callers connecting their subactors, it is the mediator connecting actors.

As an example think of your actors as airplanes and the mediator as the air traffic controller.  The air traffic controller does the coordination of communication.  In our software we want an air traffic controller to decide which airplanes should talk directly to each other and then give them a dedicated channel for communication so that the air traffic control tower isnt a bottleneck.

In this way, not all actors can talk to each other, but they can all talk to the mediator.  It is up to the mediator to assign dedicated communication channels between actors based on the type of information they want.  The communication channels can be Actor enqueuer based, or they can be any other message transport.  In fact we can write it in a way that the message publisher uses one type of message transport and the message subscriber uses another.  In this way we can pretty well decouple our actors from each other, even to the point of having one actor be an AF actor and another actor be a non-OOP producer consumer pair running in its own subVI somewhere.

0 Kudos
Message 24 of 36
(2,180 Views)

drjdpowell schrieb:

There is an alternative to both strict heirarchy and every Actor talking to one another, where Callers can "connect" their subActors, allowing communication directly between them, subject to limits set by the Caller.  This is sort of like a lot of small rooms, with one person in each room moderating the conversation.

You're right, I wrote this bit is a very "black or white" manner. Reality is gray

0 Kudos
Message 25 of 36
(2,180 Views)

The AF does allow you to create those cross connections. It does not allow you to set limits on their communication. I'm not entirely sure how a system could be created that would allow the caller to meaningfully set limits on their communication short of monitoring the communications channel for undesirable messages, but that's the same as passing messages up through the caller.

Once a comm channel exists between entities, the entities can put pretty much anything they want into that channel... even if you just give them a single integer, that's enough to send entire objects as serialized data.

0 Kudos
Message 26 of 36
(2,180 Views)

AristosQueue wrote:

I'm not entirely sure how a system could be created that would allow the caller to meaningfully set limits on their communication short of monitoring the communications channel for undesirable messages, but that's the same as passing messages up through the caller.

By "limits" I mean the ability to connect specific messages.  So if ActorA produces messages X, Y, and Z, its caller can configure it so that message Y goes to ActorB.   ActorA can thus send Y, but not any other message.   If ActorB receives an unexpected message, you know the problem is not in ActorA code, because ActorA cannot communicate with ActorB except as specified by the Caller.  In the AF this could be accomplished by some type of self-addressed message, or some other means of "guarding" ActorB's Enqueuer such that it can only send a specific message.

0 Kudos
Message 27 of 36
(2,180 Views)

Gotcha. I was thinking you meant some sort of type setting on the communications channel.

But even so, you still have to be careful... if A can communicate to B directly only with message Y, you still have to worry about steganography and extra data being pushed into that message. It's a matter of whether A *knows* it is communicating with B or whether it thinks it is communicating to its caller and the direct communication over to B is a behind-the-scenes shortcut for performance.

And you also have to worry about the order of messages being received.

A sends message X to caller.

A sends message Y to B.

Caller receives X and decides to send Z to B.

B receives Y

B receives Z

But if your thread switching is just a bit faster, you get this, with exactly the same code:

A sends message X to caller.

Caller receives X and decides to send Z to B.

A sends message Y to B.

B receives Z

B receives Y

Y and Z flip order. If there's an expectation that B will always get Y first, you have to make sure that A sends to B before it sends to caller -- but that just moves the race condition if B is communicating to caller.

These races among messages are really really nasty to debug. The explicit tree avoids the issue even coming up.

0 Kudos
Message 28 of 36
(2,180 Views)

AristosQueue wrote:

if A can communicate to B directly only with message Y, you still have to worry about steganography and extra data being pushed into that message.

As a mostly lone programmer, I have admittedly never worried about others deliberately trying to misuse the system.  I worry about me misusing the system as a shortcut, so I try and make the good way the easy way.

It's a matter of whether A *knows* it is communicating with B or whether it thinks it is communicating to its caller and the direct communication over to B is a behind-the-scenes shortcut for performance.

In the general way I program (which I argued above is quite natural) A doesn't know if its replies and notifications go anywhere.

And you also have to worry about the order of messages being received.

A sends message X to caller.

A sends message Y to B.

Caller receives X and decides to send Z to B.

...

Y and Z flip order. If there's an expectation that B will always get Y first, you have to make sure that A sends to B before it sends to caller -- but that just moves the race condition if B is communicating to caller.

These races among messages are really really nasty to debug. The explicit tree avoids the issue even coming up.

Perhaps, but I have never encountered such a bug, and this kind of message interaction is rare.  And there are many possible ways that address this. 

One way, for example, that I could have Caller to be sure Y is up-to-date re X is to bounce the Z command off X.  My actors ignore Null messages, but still call Reply on them, so I can configure a Null message to send Z as a Reply to Y, then send this message to X.  The same technique can be used to ensure a Consumer doesn't shutdown till all messages from a Producer are consumed: The Stop message to the Consumer is configured into the Reply to the Stop message to the Producer.

0 Kudos
Message 29 of 36
(2,180 Views)

drjdpowell wrote:

Perhaps, but I have never encountered such a bug, and this kind of message interaction is rare. 

You are a lucky lucky human being. They may be rare compared to bugs overall, but they are on their own common enough to be a major downfall of most UI systems I've looked at, and a significant number of control systems, with significant coding expended to prevent those situations. In my observation, nearly zero programmers are able to recognize that a piece of code has a potential problem to even think about coding a defence. It's just too easy to fall into the trap of believing that two messages sent are sent atomically, before any receivers are able to do anything, and that undefended code can work for a long long time before sabotaging everything.

These kinds of race conditions -- the kind most programmers never even contemplate -- are the primary reason the AF exists. Any framework that casually admits such races is a lesser framework in my book. I realize that it is possible for reasonable, talented programmers to hold a contrary view. There are good arguments on the other side. I just don't think those arguments are sufficiently strong enough to overcome the downside of these types of problems.

My conclusion after years of working on this before

building the AF and confirmed in the years since:

Passing all messages along the tree solves way more problems than it causes, and any frustration the developer feels with having to jump through its hoops is trivial (no matter how big it seems at the time of development) compared to the frustration saved by not having to debug the other systems.

Message 30 of 36
(2,180 Views)