Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Need some guidance on AF project

Some actor gets the new configuration (either because it is monitoring a file, a network connection, or it is a UI that the user touches). Then it sends a message to its caller actor and to any nested actors with whatever part of the changed configuration is relevant to them. Those nested actors pass send a message to their nested callers with whatever subset of the info is relevant to those nested actors.

Config data is no different from any other data. The actor that hears about the change sends a message to its relevant local neighborhood. Every actor that receives the message reacts accordingly to the change.

0 Kudos
Message 31 of 40
(2,859 Views)

NiACS - another question:

So I've got this controller actor that is a state pattern and has manual and automatic states.  It manual it accepts commands that allow you to manipulate individual hardware pieces and in automatic the only command it accepts is abort.

Right now I have a seperate GUI Actor, which at the moment is actually a nested actor of the Controller.

Now how do I get the GUI to behave differently based on which state the controller is in?  What is the cleanest way to do this?  Perhaps when I change states in the controller I send a message to the GUI to notify it as to the new state. If I recall correctly there is a hook to do something similar. As I think about it that is probably the cleanest.  Have some sort of message that sets a tab or enables/disables some controls or something.  The difference in behavior is pretty much just what data is displayed and/or what controls are enabled. 

Is using a state pattern for the GUI as well better?  Right now the GUI is the main UI window.  I guess I could have each state have its own GUI and load it into a subpanel or something.  If I had more states that might be more appealling, but for so few states...

Am I thinking about this problem correctly?  Is there an easier way?  Am I missing something?

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 32 of 40
(2,859 Views)

Taggart wrote:

Now how do I get the GUI to behave differently based on which state the controller is in? 

Since you are just talking about updating the display elements, I would avoid state pattern initially.  Just send a message to change display to a given mode, and let the UI handle it in a method call (or two).  If the complexity grows too much, you can switch over to state pattern later.

0 Kudos
Message 33 of 40
(2,859 Views)

After taking the AF class, I have a few more questions:

 

NiACS wrote:

 

 

Now, be careful here.  A lot of people use LabVIEW state machines to implement a sequence, rather than behavioral state.  That looks more like "Do step A, and use the results to determine whether you will next do step B or step C."  That isn't state pattern, it's sequencing, and sequencing *is* often best left to a helper loop.
 
How can you differentiate between these?
1.  If you want the actor to respond differently to its messages depending on its state, use the state pattern.
2.  If you want the actor to step through a series of steps, and you don't want those steps interrupted, offload the sequence into a helper loop.
3. Otherwise, just rely on your basic actor message handler.
 
These are guidelines, of course.  It is perfectly acceptable, for example, to have your actor send itself a message as part of the response to some other message.  That's no problem, provided that you can tolerate some other message from your caller or nested actor getting executed first.

 

I have several actors (5 to be exact) that need to behave as sequencers.  I have come to conclusion that the best way to implement this would be to offload it to a helper loop.  I know, use Teststand, but they are not that complicated and I don't know teststand that well...  

 

Ideally I would like to write the sequencing algorithm once.  Ie. have something where I can throw it a set of sequence steps and let it go.  I was thinking of having a sequencer actor where you can just give it a set of generic sequence steps and when you launch it, it would step through them in a helper loop.  Each sequence step would have a "Do something" method and a "Wait for Response" method.  The "Do something" could have access to the caller's queue and ask the caller to do something (and pass it an event refnum for a response).  Then the wait would wait until the caller at some point fired off the event.  So the caller would receive the request message and cache the reply refnum, until it is ready to fire it off  Then the sequencer would step to the next step.  There would some sort of generic results object or something that each step could update if it wanted. When the last step is done, the sequencer stops itself and returns the results in the last ack.

 

Then each of my actors that has to step through a sequence would have a sequencer as a nested actor. 

 

Thoughts?  Good idea?  Bad idea?  Something better?  Does something similar already exist?

thanks,

Sam

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 34 of 40
(2,672 Views)

You're in the land of reply messages, whcih always gives me pause.  Why does the sequencer need to wait for a response from the caller?  Why can it not just step through every step it has?

0 Kudos
Message 35 of 40
(2,655 Views)

I'm replacing something that was written rather sequentially.

 

It's got 4 independent stations with independent hardware that all run asynchronously with regards to each other.  But each station has a routine that it runs.

Something like:

 

turn on water valve

wait 10s

turn on mixer on low

wait until fill =x

turn mixer to hi

wait 60s

turn mixer off

 

My initial thought was each station as an actor nested with another actor that controls the whole process.  It would rotate the samples into position and then tell each station to run.  Once each station reported back that it was done, then it would rotate again and repeat.  Each station would own its own hardware, which would be a collection of nested actors.  Something like that.

 


@niACS wrote:

 Why does the sequencer need to wait for a response from the caller?  Why can it not just step through every step it has?


Well if I turn on a valve and want to wait until x amount of water has flowed before I do the next step, I've got to constantly keep checking the flowmeter, don't I, either via polling or telling it to send me updates at some rate?  Or tell the flowmeter to notify me when it reaches a specific level?  Somehow I still have to wait for that until I move to the next step... So it's not like each step can just fire off a bunch of messages and then proceed to the next.  Many of them are time-based or based off of some parameter. 

 

If I just simply do the waiting in the Actor's message handling loop aren't I "breaking" the actor framework in that ideally it should process messages "quickly" and the queue should not back up?  So I kind of need a separate loop or a helper loop, right?  Otherwise if there are a bunch of steps, I feel like the logic would get convoluted.

 

Maybe AF is not the way to do it? or maybe I'm just not thinking about the problem correctly...

 

 

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 36 of 40
(2,652 Views)

Also maybe I'm not explaining exactly what I was envisioning for a sequencer.

 

Forget having a sequencer actor for a second.

 

So say you have one of the stations.

In it's actor you have a parallel helper loop that acts as a sequencer.  It has a list of steps.  Each step sends the actor a message via the self enqueuer.  Embedded in that message is a User Event refnum.  When the actor gets that message, it does something such as: Turn on a valve.  It also caches that User Event Refnum.  

 

The actor message handling loop can then go about it's business and respond to messages.  And the helper loop is stuck sitting there waiting for the User Event to fire.   At some point, Actor's message handling loop says "oh, the water level is good" so it fires off the User Event.  (It might know the water level is good because another actor sends it a message, or maybe it gets periodic updates from the water level sensor.  Or maybe it has a periodic update message that checks the water level).  The helper loop then receives the User Event and cycles on to the next step.

 

That's basically what I'm trying to recreate.  I'm just don't want to rewrite that helper loop for 4 different stations (and for their owning actor, because it runs it's own sequence: ie. rotate into position, start each process, wait for each process to return, repeat).  So I have a nested actor that has that helper loop.  And instead of sending messages to the self-enqueuer for each step, I send them to the caller enqueuer.   And then the Sequencer Actor message handling loop really just handles a pause/unpause and abort commands.   And the actor being sequenced instead of firing off user events to pass data to one of it's own helper loops, the user event is passing data to a helper loop, but it is the helper loop of the sequencer actor.

 

Is that really trending towards reply messages?  None of the message handling loops are doing any waiting.  The waiting is occurring in a helper loop.  AND all the steps will have a timeout of somekind.  I don't think there is any risk of deadlocks, unless I'm missing something.  I would also add some kind of abort User Event that can be fired when the sequence is aborted, so if it is in the middle of waiting for 10 seconds for something to happen, it can abort immediately.

 

Am I developing some kind of anti-pattern here?  is there a better way?

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 37 of 40
(2,649 Views)

So as I'm thinking about this more: 

I really just want to recreate that helper loop.  Perhaps it makes sense to just make a reusable helper loop that I can drop into any actor and write a little library around it with some utility functions.  Then it would definitely not be breaking that actor tree as it would be a legitimate helper loop of the actor.

 

Anyone have any thoughts on that?  Anyone ever made a reusable helper loop for some purpose?

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 38 of 40
(2,624 Views)

I apologize for the delay getting back to you.

 

Looking over the previous few posts, I have a few observations:

 

1)  You can use an event structure as you have described.  It would be legit to have a user event like "Do Next Step" which you can trigger in response to stimuli.  Those aren't reply messages, because, as you have noted, your actor is idle while it is waiting for a trigger.  You aren't waiting within a method of the actor.

 

2)  You can use something like the Time Delay Message to set up your wait periods.  Set up the TDM to send yourself a message to send your event loop the "Do Next Step" event.

 

3)  Say you need to hold a step until a certain condition is met (water level = x).  Your actor must always be able to receive this message, but you don't always want to act on it.  Use the state pattern here.  Normally, receiving a water level message does nothing.  When you do a step where you need to wait for a water level, change your state somehow (boolean flag, state objects, stateful actor all work here), so that getting a water level = x message results in generating the Do Next Step event.

 

4)  If you want the same sequencer for four different sets of hardware, you can a) write the sequencer as a parent class, and fill in the hardware details in child classes or b) create a regular OO HAL for your hardware, and pass in the specific hardware object to your actor when you launch it.

 

Just some thoughts.

0 Kudos
Message 39 of 40
(2,593 Views)

Hi Guys,

 

This is an old thread, but I just thought I'd let you know that I benefited from reading through all of it. You benefited more than just the original audience.

 

Thanks,

 

-Wavepacket


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

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
Message 40 of 40
(1,501 Views)