- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Actors that do work
Thu, 2009-07-16, 20:24
Actors that do work
Hi Folks,
I am trying to figure out the best practice for an Actor that does a task (e.g. Background task, simulation, etc.) on regular basis on a changing collection or object, perhaps even as fast as possible. For example, in a game you might want to perform physical simulation repeatedly on every item as fast as possible. Before each simulation iteration, you might want to add or remove items from the scene. I haven’t seen an example like this out there in the Scala examples, so I am wondering if there is a best practice for this type of task. The solution I have in my head is something like this (using the game simulation example):
val myactor = actor {
//PhysicalObject is some sort of class where objects can be simulated
var physicalObjects = List[PhysicalObject]()
var tOld = System.nanoTime
loop {
receiveWithin(0) {
//assume these simple case classes are defined
case add(x) => physicalObjects = x :: physicalObjects
case remove(x) => physicalObjects = physicalObjects - x
}
//Do stuff here (run a simulation for example)
val tNew = System.nanoTime
val dt = (tNew – tOld) * 1E-9
for(physicalObject <- physicalObjects) physicalObject.sim(dt) //run a simulation or something
tOld = tNew
}
}
I think there are many applications in which you are repeatedly performing operations on a dynamically changing collection. This seems like it might be the right way to do it, but I am new to Scala and could be entirely wrong.
One specific question I had is this: would the above loop only receive and process one message at a time before performing the entire simulation loop? If so, is there a simple way to dispatch all messages before entering the simulation portion of the loop?
What do you think?
Thanks,
Mark
I am trying to figure out the best practice for an Actor that does a task (e.g. Background task, simulation, etc.) on regular basis on a changing collection or object, perhaps even as fast as possible. For example, in a game you might want to perform physical simulation repeatedly on every item as fast as possible. Before each simulation iteration, you might want to add or remove items from the scene. I haven’t seen an example like this out there in the Scala examples, so I am wondering if there is a best practice for this type of task. The solution I have in my head is something like this (using the game simulation example):
val myactor = actor {
//PhysicalObject is some sort of class where objects can be simulated
var physicalObjects = List[PhysicalObject]()
var tOld = System.nanoTime
loop {
receiveWithin(0) {
//assume these simple case classes are defined
case add(x) => physicalObjects = x :: physicalObjects
case remove(x) => physicalObjects = physicalObjects - x
}
//Do stuff here (run a simulation for example)
val tNew = System.nanoTime
val dt = (tNew – tOld) * 1E-9
for(physicalObject <- physicalObjects) physicalObject.sim(dt) //run a simulation or something
tOld = tNew
}
}
I think there are many applications in which you are repeatedly performing operations on a dynamically changing collection. This seems like it might be the right way to do it, but I am new to Scala and could be entirely wrong.
One specific question I had is this: would the above loop only receive and process one message at a time before performing the entire simulation loop? If so, is there a simple way to dispatch all messages before entering the simulation portion of the loop?
What do you think?
Thanks,
Mark
Thu, 2009-07-16, 21:27
#2
Re: Actors that do work
Re: [scala-user] Actors that do work
To answer my own question, I think if you put the “do this when there aren’t any messages pending” block in the case TIMEOUT that might be the right answer.
E.g.
case add(x) => as before
case remove(x) => as before
case TIMEOUT => do sim stuff here rather than outside of the receive block
This seems to make sense. Hopefully someone can confirm that this is the “right” way to solve the problem I’ve described. This also has the benefit of using reactWithin rather than receiveWithin.
-Mark
On 7/16/09 1:23 PM, "Bastian, Mark" <mbastia [at] sandia [dot] gov" rel="nofollow">mbastia@sandia.gov> wrote:
E.g.
case add(x) => as before
case remove(x) => as before
case TIMEOUT => do sim stuff here rather than outside of the receive block
This seems to make sense. Hopefully someone can confirm that this is the “right” way to solve the problem I’ve described. This also has the benefit of using reactWithin rather than receiveWithin.
-Mark
On 7/16/09 1:23 PM, "Bastian, Mark" <mbastia [at] sandia [dot] gov" rel="nofollow">mbastia@sandia.gov> wrote:
Hi Folks,
I am trying to figure out the best practice for an Actor that does a task (e.g. Background task, simulation, etc.) on regular basis on a changing collection or object, perhaps even as fast as possible. For example, in a game you might want to perform physical simulation repeatedly on every item as fast as possible. Before each simulation iteration, you might want to add or remove items from the scene. I haven’t seen an example like this out there in the Scala examples, so I am wondering if there is a best practice for this type of task. The solution I have in my head is something like this (using the game simulation example):
val myactor = actor {
//PhysicalObject is some sort of class where objects can be simulated
var physicalObjects = List[PhysicalObject]()
var tOld = System.nanoTime
loop {
receiveWithin(0) {
//assume these simple case classes are defined
case add(x) => physicalObjects = x :: physicalObjects
case remove(x) => physicalObjects = physicalObjects - x
}
//Do stuff here (run a simulation for example)
val tNew = System.nanoTime
val dt = (tNew – tOld) * 1E-9
for(physicalObject <- physicalObjects) physicalObject.sim(dt) //run a simulation or something
tOld = tNew
}
}
I think there are many applications in which you are repeatedly performing operations on a dynamically changing collection. This seems like it might be the right way to do it, but I am new to Scala and could be entirely wrong.
One specific question I had is this: would the above loop only receive and process one message at a time before performing the entire simulation loop? If so, is there a simple way to dispatch all messages before entering the simulation portion of the loop?
What do you think?
Thanks,
Mark
import scala.actors.TIMEOUT
case object Force
val myactor = actor {
loop {
receiveWithin(0) {
case Add(x) => // add item...
case Remove(x) => // remove item...
case Force | TIMEOUT => // processing x's goes here <---
}
}
}
In this version, the processing code only executes when a timeout occurs. With a timeout of 0, this will only occur when the actors mailbox is empty, and will execute repeatedly as long as it stays so. If incoming messages are fairly frequent it may help to have an additional "force timeout" message (as in the example above) that another actor can send periodically to ensure that the "timeout" code executes at least once in some specified interval.
- Colin