This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Actors that do work

2 replies
Bastian, Mark
Joined: 2009-01-16,
User offline. Last seen 42 years 45 weeks ago.
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
Colin Bullock
Joined: 2009-01-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors that do work
One answer to your question might be:

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

Bastian, Mark
Joined: 2009-01-16,
User offline. Last seen 42 years 45 weeks ago.
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:

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

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland