Easiest way to do idle handling in Scala Actor?
I have a scala actor that does some work when a client requests it. When and only when no client is active, I would like the Actor to do some background processing.
What's the easiest way to do this? I can imagine two approaches:
-
Create a new thread that wakes up and wakes up periodically. Direct approach, but I would like to avoid creating another thread (to avoid unnecessary code, complexity and overhead).
-
The Actor class has a responseWithin method that can be used to timeout the actor itself. But the documentation says the method doesn't return. So, I'm not sure how to use it.
Edit; clarification:
Suppose a background task can be broken down into smaller units that can be independently processed.
source to share
Okay, I see I need to bet 2 cents. From the author's answer, I think that "priority admission" technology is exactly what is needed here. In the section, you can find the discussion "Erlang: Priority to get a question here on SO ". The idea is to accept high priority messages first and only accept other messages when there are no high priority messages.
As Scala actors are very similar to Erlang, the trivial code to implement this would look like this:
def act = loop {
reactWithin(0) {
case msg: HighPriorityMessage => // process msg
case TIMEOUT =>
react {
case msg: HighPriorityMessage => // process msg
case msg: LowPriorityMessage => // process msg
}
}
}
It works like this. The actor has a mailbox (queue) with messages. The argument receive
(or receiveWithin
) is a partial function, and the Actor library looks for a message in the mailbox that can be applied to that partial function. In our case, it would be an object only HighPriorityMessage
. So, if the Actor library finds such a message, it applies our partial function and we process the high priority message. Otherwise, reactWithin
with a timeout of 0, it calls our partial function with an argument TIMEOUT
, and we immediately try to process any possible message from the queue (since it is waiting for a message, we cannot rule out the possibility of receiving HighPriorityMessage
).
source to share
It looks like the problem you are describing does not apply to the actor subsystem . Actor
designed for sequential processing of the message queue:
- What happens if an actor completes a background task and a new task arrives?
The actor can only find out about it, he constantly checks it mailbox
, performing a background task. How would you implement this (for example, how would you code background tasks as a unit of work so that the actor can keep interrupting and checking the mailbox)?
- What happens if the actor has many background tasks in the mailbox before the main task?
Are these background tasks removed or sent to another actor? If the latter, how can you prevent the cpu time for this actor to complete tasks?
All in all, this sounds a lot more like you need to learn some kind of networking software that can run in the background (like Data Synapse)!
source to share
Just after I asked this question, I tried some totally weird code and it seems to work fine. I'm not sure though if there is a gotcha in it.
import scala.actors._
object Idling
object Processor extends Actor {
start
import Actor._
def act() = {
loop {
// here lie dragons >>>>>
if (mailboxSize == 0) this ! Idling
// <<<<<<
react {
case msg:NormalMsg => {
// do the normal work
reply(answer)
}
case Idling=> {
// do the idle work in chunks
}
case msg => println("Rcvd unknown message:" + msg)
}
}
}
}
Explanation
Any code inside an argument loop
but prior to the call react
seems to be called when the Actor is waiting for a message. I am posting a message Idling
for myself here. In the handler for this message, I guarantee that the mailbox size is 0 before doing the processing.
source to share