Sleeping Actors without blocking in Scala

I had a bit of a hack in place, such that an Actor would sit in a loop, periodically launching messages to other Actors. This Controller Actor was no more than a few lines long, but it was also intended to handle incoming messages from other locations. The hack was simply that to manage the delay, I’d call Thread.sleep(1000), and accept that messages would simply queue up in the mailbox while the actor was blocked.

Here’s a slightly better way to do the sleeping, which doesn’t require the same blocking:

import scala.actors.Actor
import scala.actors.TIMEOUT
import scala.actors.Actor._

case object Spin
case class Log(message: String)

object SleeperTest {
  def main(args: Array[String]) : Unit = {
    val a= new SleeperTestActor.start()
    // Send kickstart message
    a ! Spin
  }
}

class SleeperTestActor extends Actor {
	def act() {
		loop {
			receive {
				case Log(message) =>
					println(message)
				case Spin =>
					this ! Log("Received spin...")
					new Sleeper(500, this).start()
					this ! Log("Gone to sleep.")
			}
		}
	}
}

class Sleeper(time: Long, origin:Actor) extends Actor {
	def act() {
		reactWithin(time) {
			case TIMEOUT =>
 				origin ! Spin
  		}
	}
}

Key to note in the output from this code is that the “Gone to sleep” message is logged directly after going to “sleep” . So, this doesn’t really sleep; it schedules an event to happen in the future, which is often much more useful.

Footnote

Posted by Stephen Strowes on Thursday, May 21st, 2009. You can follow me on twitter.

Recent Posts

(full archive)

All content, including images, © Stephen D. Strowes, 2000–2016. Hosted by Digital Ocean.