Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

AF actor is or is not a queued state machine: a discussion

[AQ Note: This long discussion was happening in another thread. I have branched it to remove the tangent from that other thread and because it seemed worthy of its own subject heading for future readers of the forums.]

The AF isn't a QSM. Actors aren't QSMs. This is critically important to understand as you begin designing any application in the Actor Framework.

[NIWeek 2013] What a Software Architect Needs to Know When Using the Actor Framework

Edit: Label for the link

Message was edited by: AristosQueue

0 Kudos
Message 1 of 34
(16,132 Views)

Are you sure about that ?  I thought I read that it was built on a QDSM or something like that?

0 Kudos
Message 2 of 34
(5,446 Views)

David Staab wrote:

The AF isn't a QSM. Actors aren't QSMs. This is critically important to understand as you begin designing any application in the Actor Framework.

This is a point of some contention. I believe very firmly that it IS a QSM. Some people -- Staab among them -- have objections to that (ab)use of the defintion. It's a philosophical difference. I think regardless of your position on the question, recognizing the aspects of it that are QSM-like are key to writing good actors.

0 Kudos
Message 3 of 34
(5,446 Views)

AristosQueue wrote:


This is a point of some contention. I believe very firmly that it IS a QSM.

Maybe I've had my head in a hole, but I wasn't aware there was disagreement here. And I'm shocked to learn that you're one of the dissenters.

0 Kudos
Message 4 of 34
(5,446 Views)

David Staab wrote:

Maybe I've had my head in a hole, but I wasn't aware there was disagreement here. And I'm shocked to learn that you're one of the dissenters.

I didn't consider it a significant point of disagreement when you and Daklu were doing your presentation. Indeed, I thought the difference of viewpoint was a good thing. But, yeah, I consider it a QSM. I agree that "generic actors are not necessarily QSMs", but I do think "actors as they are instantiated by the AF are QSMs".

An AF actor uses a queue for communication. As messages come in they are handled. There is a stateful object that is part of each message being handled. Most of my presentations include a slide sequence that starts from this slide, a very standard QSM, and proceeds to show how we start from a QSM and construct the AF, maintaining its functionality at each step of the way.

Untitled.png

In fact, I say several times in all of my webcasts that the goal of the AF is to make it easy to build the network of QSMs.

Untitled2.png

0 Kudos
Message 5 of 34
(5,446 Views)

I guess I should ask... is there a reason that you consider it a much more significant point of variation? When you and Daklu were talking on that point, my reaction was basically, "Ok, I can see their argument, but I'm not sure it matters much, and it is very useful for me when teaching new users to the AF to think of them as QSMs." Your view seemed useful for a more theoretical approach to the AF, which does open up to larger ideas, but I didn't see it as a question needing settling, which is probably why you thought I agreed -- you're used to me being vocal about disagreements like that. This one seemed minor. Did I miss something?

0 Kudos
Message 6 of 34
(5,446 Views)

Here's why I think the distiction between a QSM and an actor's message handling loop (MHL) is important:

First, many people see the standard "while loop with a dequeue into a case structure" and immediately call it a QSM.  This is, in my opinion, incorrect.  That basic code structure can be used in many different ways.  One way is as a QSM.  Another way is as a message handling loop.  The difference between a QSM and MHL is entirely in how they are used.  It has nothing to do with what the code looks like.

There is a long history of generally accepted practices accompanying QSMs that just don't work well in actor-oriented systems.  That's not to say that doing these things *always* causes problems, just that the developer runs a higher risk of painting himself into a corner if he follows that path.  This is especially true for developers who do not have a lot of experience in actor-based thinking.  Some of those dangerous practices are:

Treating the message queue as a buffer

Yes, we know the message queue acts as a buffer for unread messages.  However, treating it as a buffer opens the door for all sorts of problems, the most common of which is how to prioritize certain messages.  The QSM answer is to place the message at the front of the queue.  That can work okay as long as you only ever have one priority message, and that message is Exit.  You start walking on thin ice once you introduce additional priority messages.

The AF has priority queues, which is much better solution than enqueuing in the front, but the concept still faces architectural difficulties.  First, should a message's priority be permanantly set by the message itself, or should the sender be able to set the priority?  I believe the AF allows the sender to set the priority, which is understandable as it allows for a lot of flexibility.  Unfortunately, it allows the message sender to essentially say, "I have no idea what other messages you (the receiver) may be receiving or are in your queue, but this message is more important than all of them."  In order to make that claim, at the exact moment the message is sent the sender must know a) the relative urgency of all messages in the receiver's queue, and b) the relative urgency of all messages that will be sent to the receiver between now and the time this message is dequeued.  Clearly the sender cannot know that information, and I conclude allowing the sender to set message priority is inherently flawed.

("Flawed" does not mean useless.  Since the message sender cannot know a given message should take priority over other messages the receiver may receive, the responsibility for knowing that information falls on the developer.  I suspect most developers will never run into the problem I described, as the majority of projects are small enough for a developer to understand the entire system.  I can easily imagine this problem occurring on larger projects.)

Perhaps the most egregious problem with treating the message queue as a buffer is message chains.  This is when developers enqueue several messages with the expectation the receiver will process them in that exact order.  One of the fundamental principles of actors is "an actor can receive any message at any time."  Message chains create race conditions.  There is no way for a receiver to guarantee it will process a message chain in the exact order it was sent.  If sender 1 sends message chain a-b-c, but sender 2 happens to send message z such that the message order in the queue is a-b-z-c, things break.

Sending messages to self

Theoretically there is no problem with having a loop send message to itself, as long as each message is atomic (no message chains.)  In practice, I believe it is actually fairly easy to to accidentally create non-atomic messages when sending a message to self.  How can you tell if you've created a message chain?  Inspection and analysis is the only way I know.  The more messages a receiver can receive, that harder it is to inspect and analyze the code for correctness. 

Sending messages to self also tends to create confusing business logic that is hard to follow.  Logic that is hard to follow is a ripe location for bugs and race conditions to appear.  Better (imo) to simply avoid the risk altogether by not sending self messages.  (And it's dirt simple to avoid.)

Flow chart models

QSM thinking and sending messages to self also contribute to another problem I've been aware of for several years but haven't really figured out how to articulate well.  As near as I can tell, QSMs were developed and are most frequently used as a way to implement flow chart logic.  However, flow charts have decision points where the code will continue following one of two execution paths.  In a typical QSM implementation, the sender can only enqueue the messages that define the execution path up to the decision block.  After that the receiver has to enqueue the messages that define the next step(s) in the execution path, execution loops around to dequeue the messages, and the process continues.

When implementing a flow chart with a traditional QSM the messages are, by definition, non-atomic.  The QSM cannot receive any external messages on its queue until it finishes executing the flow chart.  What happens if the QSM is working towards a decision point and receives another message to start the flow chart?  The QSM enqueues the continuingexecution path after the new request to start the flow chart, and the QSM goes into meta-instability, where it alternates between executing the first flow chart request and the second flow chart request.

Remember that an actor's message handling loop must be written so it can receive any message at any time without becoming meta-instable.  QSMs, especially QSMs written to implement flow charts, often cannot deal with that requirement.  QSM's can work well when there is exactly one entity putting items on its queue, such as the JKI SM (which is a combination of QSM and MHL, and all QSM states are self-enqueued.)  It is possible to make them work with one (or more) external enqueuers, but it requires a more complex message protocol and isn't without its own pitfalls.  IMO, flow chart QSMs are wholly inadequate for an actor's message handling loop. 

QSMs can certainly be used in an actor as a helper loop, just not as an actor's message handling loop.

-------

When you say, "I'm not sure it matters much and it's useful when teaching the AF," I think I get where you're coming from.  There are a lot of new concepts in the AF and relating it to something familiar can ease the transition.  On the other hand, I believe understanding the weaknesses of QSM thinking and writing an actor MHL (and messages) in a way that avoids those problems is critical to implementing robust actor-oriented systems.  As much as the AF nudges users in the right direction, it can't prevent a developer with a QSM mindset from implementing poorly designed messages and message handling loops, and end up having the same problems as traditional QSMs.

[Edit - To clarify, I don't view an AF actor as necessarily being a QSM.  It can become a QSM with poorly written message handling code, chaining messages, etc., but by default I don't consider it a QSM.]

[Edit 2 - Despite the length of my explanation and my preference for distinguishing between QSMs and MHLs, I recognize Staab and I are in the minority and unlikely to change the terminology of the community as a whole.  And while I believe we'd all be better off by better naming, more precise definitions, and discarding the baggage associated with QSMs, "is a message handling loop a QSM?" isn't really a soapbox issue for me.  A tuna can issue, yes... soapbox, no.]

Message 7 of 34
(5,446 Views)

Hi Daklu,

Could you expand on how it's "dirt simple to avoid" sending self messages? I have a whole class of UI actors that send messages to themselves to handle front panel events and to update controls with calculation results, and I really can't think of an easy way to avoid doing that.

CLAD
0 Kudos
Message 8 of 34
(5,446 Views)

@wegunterjrNGC I hope you don't mind this tangenting of your thread. I'll move all these into a separate discussion thread if you like.

Daklu: First, good... my understanding of your position seems to have been correct. As I said, yours is a more general approach that does put the system on more sound mental foundation.

Having said that... if you tell people it is not a state machine and merely a message handler, although this may help with them understanding the message transmission part, so well described in your objection, you deny them a deeper understanding of the stateful actor object at the heart of the loop. The fact that the object maintains a state and that state is changed by the receipt of messages is a key to designing a good actor. It allows you to better understand innovations like "handling" a message by reading it but not actually acting on it until some other state has been achieved. The State Pattern can be used to simplify some fairly complex actors precisely because it is a state machine.

There's a favorite koan of mine that applies here:

The master called to the student. When the student approached, the master demanded, "Quick! What is this in my hand?!"

The student answered, "It is your walking stick, master."

"You are correct, but this is not a walking stick."

The master began to beat the student for the answer. On the third stroke, the student became enlightened. What had the student discovered?

Traditionally, you should pause for at least a day after reading a koan to meditate before claiming to have any answer to its question and before asking for any help in answering it. They are often confusing, sometimes violent, but generally deeply insightful. But perhaps this koan can be understood more easily in light of the current discussion.

Message 9 of 34
(5,446 Views)

PS: Daklu, any need for atomic handling of messages "a then b then c without allowing an intervening z" can be achieved with the Batch Msg class. I don't know if you've seen that one ... it's not part of the AF library, but it has shipped alongside the library since the second version.

0 Kudos
Message 10 of 34
(5,446 Views)