Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Avoid sending messages to self *from within the message handling loop*

Daklu wrote:


I've used the notifier to pass information to the helper loop like you described, and agree it works well as long as the helper loop is kept simple.  If you get into a situations where you're casing out to different procedures based on a data in the notifier, you're better off refactoring it into a real actor.

One can also make a helper loop that is a "worker" sitting behind a job queue, possibly augmented with an "abort" notifier.  I don't view every message-handling loop as naturally being an "actor". 

Message 11 of 21
(2,861 Views)
drjdpowell wrote:

One can also make a helper loop that is a "worker" sitting behind a job queue, possibly augmented with an "abort" notifier. 

Job queues are another concept that can be combined with loops in several different ways, but in this case I don't think a job queue is necessary.

drjdpowell wrote:

I don't view every message-handling loop as naturally being an "actor". 

I agree every message handling loop isn't necessarily an actor.  It is possible to use messages plus other techniques (notifiers, globals, etc.) to transfer data to any message handling loop, and (arguably) that makes it not an actor.

When I add message handling to a loop, I make a conscious decision to treat it as an actor.  That means I convert all data transfers to messages, add appropriate error handling, etc.  IMO that makes it easier to manage complexity and make sure there are no hidden race conditions.

Message 12 of 21
(2,862 Views)

Thanks for all the tips!

It feels comfortable and gives confidence to get to know how you both would or did handle a situation like this. I'll consider using a notifier and switch to a full nested actor only if no other solutions work (or look too ugly).

0 Kudos
Message 13 of 21
(2,862 Views)

@Daklu wrote:

@drjdpowell wrote:

One can also make a helper loop that is a "worker" sitting behind a job queue, possibly augmented with an "abort" notifier. 

Job queues are another concept that can be combined with loops in several different ways, but in this case I don't think a job queue is necessary.

You mentioned that if the loop gets more complex than the notifier-driven example, then you refactor as an "actor".  But I believe that there are use cases of more complex "helper" loops that should not be "actors".  Actors run under restrictions, restrictions intended to allow them to scale up to many interacting processes, often processes that different "modules", designed at different times and perhaps by different people, and being things that need to be loosly coupled to each other.  These are great benefits, but when one is focused on a few loops interacting to form a single cohesive module, the benefits may be outweighed by the increased flexibility of being able to design whatever best suits the task. 

I once had to make an actor to run a USB2000 spectrometer.  The driver VIs I had were synchronous with the unit, so if I asked for a 10 second spectrum, I had a blocking call of 10 seconds.  Not acceptable in an actor, so I made a "nested actor" to actually call the unit, supervised by the main actor.  But my nested "actor" wasn't really an actor, it was a helper loop that followed some, but not all, actor principles.  In hindsight, calling it an "actor" was a mistake, it should have been more clearly a dedicated helper loop, even if it was actor-like in some ways.

0 Kudos
Message 14 of 21
(2,862 Views)

drjdpowell wrote:

You mentioned that if the loop gets more complex than the notifier-driven example, then you refactor as an "actor". But I believe that there are use cases of more complex "helper" loops that should not be "actors".

If you change "should not" to "need not," then I agree 100%.  A lot of it depends on how you want to manage the project's complexity. 

I did not mean to imply the helper loop should be refactored into an actor if it is made any more complex.  It's up to each designer to make up their own decisions on when a helper loop should be refactored into an actor.  I prefer to be slightly conservative in this regard, so for me that point comes when I start sending messages to the helper loop.

0 Kudos
Message 15 of 21
(2,862 Views)

Daklu wrote:


I prefer to be slightly conservative in this regard, so for me that point comes when I start sending messages to the helper loop.

Would you count sending "jobs" to a "worker" via a job queue as being sending "messages"? 

Message 16 of 21
(2,862 Views)

drjdpowell wrote:

Would you count sending "jobs" to a "worker" via a job queue as being sending "messages"?

No, *I* don't, because a worker loop isn't a messsage handling loop, a job queue isn't a message transport (queue,) and a job isn't a message.

In my actor model, the purpose of messages is to tranfer data between actors as quickly as possible so each actor can make its decisions based on the most up-to-date information available.  Message handling loops are designed to process messages quickly so messages don't stack up in the queue.  Lengthy processes are delegated to helper loops.  Lastly, actors should rarely, if ever, have reason to manipulate their own queue, and they should never manipulate the queue of a different actor.

The goal of a job queue and worker loop is to process the jobs as quickly as possible.  Like on a factory floor, if ia worker goes idle you're losing money.  In order to keep the worker loop busy you could, for example, start the worker loop by queuing up 5 jobs and periodically checking the queue status.  Whenever there's less than two jobs remaining on the queue you enqueue 5 more jobs.

When a shutdown request comes from above you could pull the unstarted jobs off the queue, place them back on the list of jobs to be done.  When the worker loop finishes the last job it is working on, the control loop (probably a message handling loop) stops the worker loop, exits itself, and sends a message up to its controller that everything has stopped.

So while your worker loop could look exactly like your message handling loops and your job could be the same Labview type as your message, the way in which they are used, what you're allowed to do with them, and the expectations you have for each of them are entirely different.

Message 17 of 21
(2,862 Views)

Daklu wrote:

drjdpowell wrote:

Would you count sending "jobs" to a "worker" via a job queue as being sending "messages"?

...

Following onto Dave's good answer, a Worker can receive data (asynchronously) that contains references, whereas an Actor ought to only be receiving messages that are serializable with by-val semantics. Maybe a Job inherits from Message, or happens to be a Message, or not even related to a Message. The worker is the model of concurrency in a private, bounded context, and because of these constraints does not necessarily go to the extent of protecting itself from outside "attacks" that an Actor might be subjected to. A Worker is likely more capable of being an instance in a Worker Pool (or Worker Cluster, as long as the application space allows parallelization), whereas an Actor is less likely to be part of an Actor Cluster (since, in LabVIEW, I reckon many of our application spaces involve Actors wrapping physical and/or virtual resources that physically don't make sense sitting behind a load balancer).

So, Actor is to Message as Worker is to Job, where there are likely syntax similaries, but perhaps significantly different semantics.

Message 18 of 21
(2,862 Views)

Daklu wrote:

drjdpowell wrote:

Would you count sending "jobs" to a "worker" via a job queue as being sending "messages"?

No, *I* don't, because a worker loop isn't a messsage handling loop, a job queue isn't a message transport (queue,) and a job isn't a message.

Ah, your using a more specific definition of a message than I am, then. 

0 Kudos
Message 19 of 21
(2,862 Views)
drjdpowell wrote:

Ah, your using a more specific definition of a message than I am, then.

In this context, yes.  In the abstract, a "message" could be any data communicated between loops regardless of how the data is used or what the transport mechanism is.  There are times when that's what I mean when I say "message," but this isn't one of them.

0 Kudos
Message 20 of 21
(2,862 Views)