Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Self Messaging Actors

I've started playing around with the actor framework and come upon a solution that works but not sure how efficient it its. I wanted to make a generic timer actor to be used with several projects and instead of having a loop or anything of the sort in the Actor Core I instead tied the reply queue with the return queue and thus simply sent messages back to itself. I've attached the code (without any UI so you wont be able to see the functionality in action). Is this efficient or am I just doing it the hard way?

How it essentially works is you initialize the Class with the Duration (ms) you want and then launch the actor and send the Start Message. In the Actor Core I tied the return and reply queues togeather so that in the Check Message action it checks to see if the Duration has passed and if not "replys" to check the duration again. If the Duration has passed then it stops the Actor and then sends out a message to the origionally supplied Reply queue.

If you have questions feel free to ask.

*Updated the ZIP file to include Messages*

Download All
0 Kudos
Message 1 of 12
(8,224 Views)

So, it is in a tight loop posting messages to itself until time has elapsed?  The StartMessage class was not included in your zip file so I cannot see what it's Do.vi is, um, Do-ing.  Does it wait a bit before posting to the reply queue (itself)? 

This is essentially a polling loop which to me is not a very good implementation.

It also seems like a bit of overhead to create an actor only for it to die after a delay, yet I do like the simplicity.

I would prefer to see a Timer actor that sticks around for ever and other actors register to be notified when the time their 'wake-up' call has occurred or perhaps do the SASEs at that time.  It does add some (well maybe more than some) complexity to the Timer actor.  It would require the actor to have a process loop that should not poll but execute on the next logical time based on the list of registared recipients.

Kurt

0 Kudos
Message 2 of 12
(4,665 Views)

My apologies about the StartMessage... all it does is pass in a starting time stamp and then initiates the Check time loop.

The point of the Timer was a "fire and forget" type process. I'd set the duration I want it to last, input the messages it wanted it to send when it was done, then just fire it once and forget about handling it from there on out. Since each timer would be asyncronous and reentrent I'd be able to fire off as many as I want with whatever duration I wanted directed at different Actors.

Not sure how to better do this without polling... I did add the wait time so it didnt tie up too much processor.

Any suggestions on how to change this from polling would be helpful.

0 Kudos
Message 3 of 12
(4,665 Views)

I do not have any good suggestions that would keep it as simple as this.  Sometimes a simple solution is good, bear in mind that while the StartMessage.Do has a timer waiting, then it will not be able to respond to any new messages until it is done.  The only message likely would be some sort of shutdown message.  If your timer value is long, though it will not miss handling the shutdown message, it will be delayed.

You have something that works, you know its implementation strengths and weaknesses, and you can address any changes in the future without affecting the existing calling actors - all good.

I'll keep thinking about it though.

0 Kudos
Message 4 of 12
(4,665 Views)

You are correct that the only outside message the Timer would be interested in is an early shutdown message. At least in the application that I use it in if there ever is an early shutdown the processes that the Timer would normally respond to are handled elsewhere so it doesn't matter how long it needs to wait before finally shutting itself down.

While the Timer works for me I am more interested in seeing if the cycling Actor format I used was much of an issue. Another place I found use for it was hardware polling. I set up a similar "loop" gathering a waveform at a specific interval and send it out on a separate Waveform Queue. It continues running until the Waveform Queue becomes invalid (the information is no longer needed/wanted) then shuts itself down. I use it in this format again so I can "fire-and-forget" the hardware side of things and just deal with the information coming in on the Waveform Queue, essentially abstracting where I get the information from and where I actually use it.

In situations like this is my Actor loop just adding unnecessary complexity that could more easily be done in a simple loop in the Actor Core method?

0 Kudos
Message 5 of 12
(4,665 Views)

I have one possible suggestion.

My thought, on reading your post, was that it would be better if the process that was going to send the message wasn't using up CPU cycles constantly checking "is it time yet?" So I started plotting backwards to see if I could come up with something.

If the goal is to have something asleep that sends the message after X milliseconds,  the block diagram will look something like a Flat Sequence with "Wait Milliseconds" in the first frame and Enqueue in the second frame. Problem: There's no way to wake up that sleeping Wait Milliseconds. So, replace the Wait Milliseconds with a Wait On Notifier with a timeout set to X. If no one sends the notification, the node proceeds to enqueue. If a notification does arrive (or arrived before it started waiting), the node skips the enqueue. Even nicer, we can get rid of the Flat Sequence and just connect the Error terminals. 🙂

Ok, now we have a way to wake up midway through the timeout. But the whole thread that is doing this is tied up... but in LV 2011, we have a good solution for this... the Start Asynch Call By Reference node.  (Optional: You could make the message have meaning -- if you send True, it means stop waiting and send the message immediately. Send false to mean stop waiting and drop the message.)

We can write a reentrant VI that takes a Message, a Send Queue, a Timeout and a Notifier as input, waits on the notifier and if it times out it enqueues the message. But whose job is it to spawn the reentrant clones of this VI? Whose job is it to fire the notifier?  (Option 2: A fourth parameter to tell the subVI to just send the message once, send it N times or send it infinitely until told to stop by the notifier.)

Two possible solutions that I can think of:

1. We create a special "Timed Postman Actor.lvclass". This actor has a single Notifier. He handles one message: Timed Message.lvclass. Timed Message is a lot like Batch Message -- it wraps another message and the Do.vi for Timed Message starts the asynch call by ref described above. Timed Postman Actor in Stop Core sends to the Notifier. Thus whenever the Timed Postman stops, all the waiting timed messages time out.

2. Create a Send Timed Message.vi which takes a Send Queue and a Message as input. On its diagram it creates a new Notifier and then calls Start Asynch Call By Ref. It then returns the Notifier to its caller. Now the caller has a way to abort the message if it so chooses.

Are either of those two approaches acceptable?

0 Kudos
Message 6 of 12
(4,665 Views)

DukeGriffin wrote:

In situations like this is my Actor loop just adding unnecessary complexity that could more easily be done in a simple loop in the Actor Core method?

I think yes. I did the "loop inside Actor Core" solution in my offline demo in the temperature sensor, which checks the temperature and announces it ever 5 seconds. Worked well and seems like less work than what you're describing.

0 Kudos
Message 7 of 12
(4,665 Views)

Ok... you hit me with an interesting problem, curse you, so it ate my evening. 😉

I coded up my Option #2... but I can't attach it here... so I'm going to edit your original post to add another attachment. So look for it up there.  Useful?  (Unzip the file and open "TEST Timed Delivery.vi" )

0 Kudos
Message 8 of 12
(4,665 Views)

That actually makes a lot of sense in how its handled. Combine that with the fact you solved another issue I was having in sending a specific message periodically without having to tie it in with an outside loop. What you wrote could be used as either a time delayed message or a periodic message source.

After looking at how I incorporated my timer actor into my project however I don't think this will be able to replace it. In my project I wasn't using the Timer actor just as a way to fire off a message after a certain amount of time but also to update a FP control with the amount of time left... in doing this I almost require the timer to be polling so it can constantly update the time remaining. So I might be able to reduce some of the complexity by making it a loop in the Actor Core but sadly at least this project requires the polling to update a FP control.

In either case thanks for your late night. Your solution will definitely come in handy several other areas of my project.

0 Kudos
Message 9 of 12
(4,665 Views)

I used a Notifier as my wait... you could easily adapt the VI to use an Event Structure instead of the Wait For Notification node and give it a Timeout case in which you send a different message (i.e., "Update Front Panel").

Good luck, and I'm glad to hear this is working for you.

0 Kudos
Message 10 of 12
(4,665 Views)