diff --git a/akka-samples/akka-sample-ants/src/main/scala/Ants.scala b/akka-samples/akka-sample-ants/src/main/scala/Ants.scala index 371a7792b0..f1cc0ba628 100644 --- a/akka-samples/akka-sample-ants/src/main/scala/Ants.scala +++ b/akka-samples/akka-sample-ants/src/main/scala/Ants.scala @@ -7,13 +7,13 @@ package sample.ants import java.util.concurrent.TimeUnit import scala.util.Random.{nextInt => randomInt} import se.scalablesolutions.akka -import akka.actor.{ActorRef, Transactor, Scheduler} +import akka.actor.{Actor, ActorRef, Scheduler} import akka.actor.Actor.actorOf import akka.stm.local._ object Config { val Dim = 80 // dimensions of square world - val AntsSqrt = 7 // number of ants = AntsSqrt^2 + val AntsSqrt = 20 // number of ants = AntsSqrt^2 val FoodPlaces = 35 // number of places with food val FoodRange = 100 // range of amount of food at a place val PherScale = 10 // scale factor for pheromone drawing @@ -41,7 +41,7 @@ case class Cell(food: Int = 0, pher: Float = 0, ant: Option[Ant] = None, home: B object EmptyCell extends Cell class Place(initCell: Cell = EmptyCell) extends Ref(Some(initCell)) { - def cell: Cell = get.get + def cell: Cell = getOrElse(EmptyCell) def food: Int = cell.food def food(i: Int) = alter(_.addFood(i)) def hasFood = food > 0 @@ -58,6 +58,8 @@ class Place(initCell: Cell = EmptyCell) extends Ref(Some(initCell)) { def home: Boolean = cell.home } +case object Ping + object World { import Config._ @@ -66,6 +68,10 @@ object World { lazy val ants = setup lazy val evaporator = actorOf[Evaporator].start + private val snapshotFactory = TransactionFactory(readonly = true, familyName = "snapshot") + + def snapshot = atomic(snapshotFactory) { Array.tabulate(Dim, Dim)(place(_, _).get) } + def place(loc: (Int, Int)) = places(loc._1)(loc._2) private def setup = atomic { @@ -81,12 +87,12 @@ object World { } def start = { - ants foreach (pingEvery(_, AntMillis)) - pingEvery(evaporator, EvapMillis) + ants foreach pingEvery(AntMillis) + pingEvery(EvapMillis)(evaporator) } - private def pingEvery(actor: ActorRef, millis: Long) = - Scheduler.schedule(actor, "ping", Config.StartDelay, millis, TimeUnit.MILLISECONDS) + private def pingEvery(millis: Long)(actor: ActorRef) = + Scheduler.schedule(actor, Ping, Config.StartDelay, millis, TimeUnit.MILLISECONDS) } object Util { @@ -121,9 +127,9 @@ object Util { } } -trait WorldActor extends Transactor { +trait WorldActor extends Actor { def act - def receive = { case "ping" => act } + def receive = { case Ping => act } } class AntActor(initLoc: (Int, Int)) extends WorldActor { @@ -131,13 +137,17 @@ class AntActor(initLoc: (Int, Int)) extends WorldActor { import Util._ val locRef = Ref(initLoc) + + val name = "ant-from-" + initLoc._1 + "-" + initLoc._2 + implicit val txFactory = TransactionFactory(familyName = name) + val homing = (p: Place) => p.pher + (100 * (if (p.home) 0 else 1)) val foraging = (p: Place) => p.pher + p.food - def loc = locRef.get.getOrElse(initLoc) + def loc = locRef.getOrElse(initLoc) def newLoc(l: (Int, Int)) = locRef swap l - def act = { + def act = atomic { val (x, y) = loc val current = place(x, y) for (ant <- current.ant) { @@ -200,6 +210,11 @@ class AntActor(initLoc: (Int, Int)) extends WorldActor { class Evaporator extends WorldActor { import Config._ import World._ + + implicit val txFactory = TransactionFactory(familyName = "evaporator") val evaporate = (pher: Float) => pher * EvapRate - def act = for (x <- 0 until Dim; y <- 0 until Dim) place(x, y) pher evaporate + + def act = for (x <- 0 until Dim; y <- 0 until Dim) { + atomic { place(x, y) pher evaporate } + } } diff --git a/akka-samples/akka-sample-ants/src/main/spde/Ants.spde b/akka-samples/akka-sample-ants/src/main/spde/Ants.spde index 2cbb7ae44d..05565673d6 100644 --- a/akka-samples/akka-sample-ants/src/main/spde/Ants.spde +++ b/akka-samples/akka-sample-ants/src/main/spde/Ants.spde @@ -8,13 +8,13 @@ size(Dim * scale, Dim * scale) smooth() override def setup() { - background(255) + background(255) World.start } def draw() { - for (x <- 0 until Dim; y <- 0 until Dim) { - val cell = atomic { World.place(x, y).cell } + val world = World.snapshot + for (x <- 0 until Dim; y <- 0 until Dim; cell <- world(x)(y)) { val (rx, ry, rw, rh) = (x * scale, y * scale, scale, scale) noStroke() fill(255) @@ -39,7 +39,7 @@ val s = scale - 1 val m = s / 2 def antLine(dir: Int) = dir match { - case 0|4 => (m, 0, m, s) + case 0|4 => (m, 0, m, s) case 1|5 => (s, 0, 0, s) case 2|6 => (s, m, 0, m) case _ => (s, s, 0, 0)