Saturday, March 3, 2012

Akka Spaces Revisited






Expect frequent changes.





AkkaSpace


The idea behind this Akka Space library is, again, (as its name suggests) to implement Local Akka Spaces and Remote Akka Spaces (in another way than in the previous posts).

Note: this post is, again, self contained, so, some code similar to code of previous posts has been repeated.

I have (temporarily) given up the idea to make use of partial functions for pattern matching. On the one hand this is a pity (the { case pattern => code } idiom looks like a very appealing one to me). On the other hand, remotely the idiom comes with issues (locally it works as a charm).

In this post I make use of (less powerful) equality insead of pattern matching. Luckily, both the pingpong table and the stick table examples can elegantly be implemented using equality (the full power of pattern matching is not needed).

Note: in the previous Remote Akka Spaces post I forgot to clean up the space when space actors have finished using the space (for example, when pingers and pongers have finished using the pingpong table).






Messages


case class Put[A](a: A)

case class Reg[A](b: A)

case class PutCleanup[A](as: Vector[A])

case class RegCleanup[A](bs: Vector[A])

case class Get[A](a: A)



The case classes Put[A] and Reg[A] model messages that a space actor can send to a space.


The case classes PutCleanup[A] and RegCleanup[A] model messages that a space actor can send to a space (typically when it has finished using the space).


The case class Get[A] models messages that a space can send back to a space actor.






Space


class Space[A](spaceSystem: ActorSystem) extends Actor {
val log = Logging(context.system, this)

private val pva = Agent(Vector[A]())(spaceSystem)
private val rva = Agent(Vector[(A, ActorRef)]())(spaceSystem)

implicit val timeout = new Timeout(1000)

override def toString =
"\n\n Put: " + pva.await +
"\n Reg: " + (rva.await map { case (a, _) => a }) +
"\n Reg (actor refs): " + (rva.await map { case (_, ar) => ar }) +
"\n"

private def put(a: A) =
atomic {
_ =>
rva.await find { case (b, _) => a == b } match {
case None =>
pva send (_ :+ a)
log.info("" + this)
case Some(r) =>
val (b, ar) = r
rva send (_ diff Vector(r))
log.info("" + this)
ar ! Get(a)
}
}

private def reg(b: A, ar: ActorRef) =
atomic {
_ =>
pva.await find { case a => b == a } match {
case None =>
val r = (b, ar)
rva send (_ :+ r)
log.info("" + this)
case Some(a) =>
pva send (_ diff Vector(a))
log.info("" + this)
ar ! Get(a)
}
}

private def putCleanup(as: Vector[A]) =
atomic {
_ =>
val pv = pva.await
val fpv = for {
a <- pv; if (as contains a)
} yield a
pva send (_ diff fpv)
log.info("" + this)
}

private def regCleanup(bs: Vector[A]) =
atomic {
_ =>
val rv = rva.await
val frv = for {
r @ (b, _) <- rv; if (bs contains b)
} yield r
rva send (_ diff frv)
log.info("" + this)
}

def receive = {
case Put(a: A) => put(a)
case Reg(b: A) => reg(b, sender)
case PutCleanup(as: Vector[A]) => putCleanup(as)
case RegCleanup(bs: Vector[A]) => regCleanup(bs)
case other => sys.error("space: this should never happen")
}
}



A space processes Put[A] and Reg[A] messages.
The space has two vectors of agents


  • pva: a vector of (agents of) puts to be matched to regs
  • rva: a vector of (agents of) regs to be matched to puts

When receiving a put

  • when there is no matching reg, the put is added to the vector of puts
  • when there is a matching reg, the put is sent back to its sender

When receiving a reg

  • when there is no matching put, the reg is added to the vector regs
  • when there is a matching put, the put is sent back to its sender

When receiving a put cleanup

  • remaining matching puts are cleaned up

When receiving a reg cleanup

  • remaining matching regs are cleaned up






SpaceActor


abstract class SpaceActor[A] extends Actor {
initialState()

var pf: PartialFunction[A, Unit] = _

protected def initialState(): Unit

private def get(a: A) {
pf apply a
}

def receive = {
case Get(a: A) => get(a)
case other => sys.error("space actor: this should never happen")
}
}



A space actor processes Get[A] messages.
The space actor has a partial function.
The space actor processes a message by applying its partial function to the message argument.


A space actor starts in its (to be defined) initial state.






PingPongTableApp


We are ready for a first application PingPongTableApp.






PingPong


sealed abstract class PingPong

case class Ping() extends PingPong

case class Pong() extends PingPong

case class KoPing() extends PingPong

case class KoPong() extends PingPong

case class OkPing() extends PingPong

case class OkPong() extends PingPong



The sealed abstract class PingPong and the case classes implementing it model the data that drive the application.






PingPongTable


import akka.actor.ActorSystem

case class PingPongTable(spaceSystem: ActorSystem)
extends Space[PingPong](spaceSystem) {
}



The case class PingPongTable models the pingpong table.






Pingers and Pongers


case class Pingers(pingPongTableRef: ActorRef, numberOfPingers: Int)
extends SpaceActor[PingPong] {
val log = Logging(context.system, this)

val pingers = for { i <- 1 to numberOfPingers } yield {
context.actorOf(
Props(Pinger(pingPongTableRef)),
name = "pinger_" + i)
}

def playingState() {
pf = {
case KoPing() =>
log.info("ko")
pingPongTableRef ! Put(OkPong())
log.info("pingers shutdown")
pingPongTableRef ! RegCleanup(Vector(OkPing(), Pong()))
pingersSystem.shutdown()
case OkPing() =>
log.info("ok")
log.info("pingers shutdown")
pingPongTableRef ! RegCleanup(Vector(KoPing(), Pong()))
pingersSystem.shutdown()
}

pingPongTableRef ! Reg(KoPing())
pingPongTableRef ! Reg(OkPing())
}

def initialState() {
playingState()
}

override def preStart() {
pingPongTableRef.!(Put(Ping()))(pingers.head)
}
}

case class Pongers(pingPongTableRef: ActorRef, numberOfPongers: Int)
extends SpaceActor[PingPong] {
val log = Logging(context.system, this)

val pongers = for { i <- 1 to numberOfPongers } yield {
context.actorOf(
Props(Ponger(pingPongTableRef)),
name = "ponger_" + i)
}

def playingState() {
pf = {
case KoPong() =>
log.info("ko")
pingPongTableRef ! Put(OkPing())
log.info("pongers shutdown")
pingPongTableRef ! RegCleanup(Vector(OkPong(), Ping()))
pongersSystem.shutdown()
case OkPong() =>
log.info("ok")
log.info("pongers shutdown")
pingPongTableRef ! RegCleanup(Vector(KoPong(), Ping()))
pongersSystem.shutdown()
}

pingPongTableRef ! Reg(KoPong())
pingPongTableRef ! Reg(OkPong())
}

def initialState() {
playingState()
}
}

case class Pinger(pingPongTableRef: ActorRef)
extends SpaceActor[PingPong] {
def pingState() {
val log = Logging(context.system, this)

pf = {
case Pong() =>
Thread.sleep(round(1000 * random))
if (random < 0.95) {
log.info("ping")
pingPongTableRef ! Put(Ping())
pingState()
} else {
log.info("no ping")
pingPongTableRef ! Put(KoPing())
}
}

pingPongTableRef ! Reg(Pong())
}

def initialState() {
pingState()
}
}

case class Ponger(pingPongTableRef: ActorRef)
extends SpaceActor[PingPong] {
def pongState() {
val log = Logging(context.system, this)

pf = {
case Ping() =>
Thread.sleep(round(1000 * random))
if (random < 0.95) {
log.info("pong")
pingPongTableRef ! Put(Pong())
pongState()
} else {
log.info("no pong")
pingPongTableRef ! Put(KoPong())
}
}

pingPongTableRef ! Reg(Ping())
}

def initialState() {
pongState()
}
}



A pinger starts in its ping state receiving a Pong from a ponger. This can either succeed, in which case he puts a Ping on the pingpong table and stays in its ping state, or fail, in which case he puts a KoPing on the pingpong table.


A ponger starts in its pong state receiving a Ping from a pinger. This can either succeed, in which case he puts a Pong on the pingpong table and stays in its pong state, or fail, in which case he puts a KoPong on the pingpong table.


The pingers supervisor creates pingers and starts in its playing state receiving a KoPing from a pinger, in which case he puts an OkPong on the pingpong table and cleans up, or an OkPing from a pongers supervisor, in which case he cleans up.


The pongers supervisor creates pongers and starts in its playing state receiving a KoPong from a ponger, in which case he puts an OkPing on the pingpong table and cleans up, or an OkPong from a pingers supervisor, in which case he cleans up.


Note: in the preStart of the pingers supervisor, a ping is put on the pingpong table.






PingPongTableApp


object PingPongTableGlobal {
val pingPongTableSystem = ActorSystem(
"PingPongTable",
ConfigFactory.load.getConfig("pingPongTable"))
}

class PingPongTableApplication extends Bootable {
val pingPongTableRef = pingPongTableSystem.actorOf(
Props(PingPongTable(pingPongTableSystem)),
name = "pingPongTable")

def startup() {
}

def shutdown() {
pingPongTableSystem.shutdown()
}
}

object PingPongTableApp {
def main(args: Array[String]) = {
val application = new PingPongTableApplication
}
}



The pingpong table app simply installs a pingpong table.






PingersApp and PongersApp


object PingersGlobal {
val pingersSystem = ActorSystem(
"Pingers",
ConfigFactory.load.getConfig("pingers"))
}

class PingersApplication extends Bootable {
val pingPongTableRef = pingersSystem.actorFor(
"akka://PingPongTable@127.0.0.1:2552/user/pingPongTable")

val numberOfPingers = 2

val pingersRef = pingersSystem.actorOf(
Props(Pingers(pingPongTableRef, numberOfPingers)),
name = "pingers")

def startup() {
}

def shutdown() {
pingersSystem.shutdown()
}
}

object PingersApp {
def main(args: Array[String]) = {
val application = new PingersApplication
}
}

object PongersGlobal {
val pongersSystem = ActorSystem(
"Pongers",
ConfigFactory.load.getConfig("pongers"))
}

class PongersApplication extends Bootable {
val pingPongTableRef = pongersSystem.actorFor(
"akka://PingPongTable@127.0.0.1:2552/user/pingPongTable")

val numberOfPongers = 2

val pongersRef = pongersSystem.actorOf(
Props(Pongers(pingPongTableRef, numberOfPongers)),
name = "pongers")

def startup() {
}

def shutdown() {
pongersSystem.shutdown()
}
}

object PongersApp {
def main(args: Array[String]) = {
val application = new PongersApplication
}
}



The pingers app simply looks up a pingpong table and installs a pingers supervisor.

The pongers app simply looks up a pingpong table and installs a pongers supervisor.






Configuration


//# common.conf
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty {
hostname = "127.0.0.1"
}
}
}

//# application.conf
pingPongTable {
include "common"

akka {
remote.netty.port = 2552
}
}

pingers {
include "common"

akka {
remote.netty.port = 2553
}
}

pongers {
include "common"

akka {
remote.netty.port = 2554
}
}





Running the PingPongTableApp, PongersApp and PingersApp


Running the apps produces something like below.




[info] Running akka.space.PingPongTableApp
[INFO] [03/03/2012 22:28:31.327] [run-main] [ActorSystem(PingPongTable)]
REMOTE: RemoteServerStarted@akka://PingPongTable@127.0.0.1:2552
[INFO] [03/03/2012 22:28:39.229] [PingPongTable-6] [ActorSystem(PingPongTable)]
REMOTE: RemoteClientStarted@akka://Pongers@127.0.0.1:2554
[INFO] [03/03/2012 22:28:39.320] ... [...pingPongTable]

Put: Vector()
Reg: Vector()

[INFO] [03/03/2012 22:28:39.339] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong())

[INFO] [03/03/2012 22:28:39.341] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong())

[INFO] [03/03/2012 22:28:39.342] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping())

[INFO] [03/03/2012 22:28:50.809] [PingPongTable-7] [ActorSystem(PingPongTable)]
REMOTE: RemoteClientStarted@akka://Pingers@127.0.0.1:2553
[INFO] [03/03/2012 22:28:50.821] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), Ping())

[INFO] [03/03/2012 22:28:50.826] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), Ping(), KoPing())

[INFO] [03/03/2012 22:28:50.834] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), Ping(), KoPing(), OkPing())

[INFO] [03/03/2012 22:28:50.835] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), Ping(), KoPing(), OkPing(), Pong())

[INFO] [03/03/2012 22:28:50.841] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), Ping(), KoPing(), OkPing(), Pong(), Pong())

[INFO] [03/03/2012 22:28:51.621] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), KoPing(), OkPing(), Pong(), Pong())

[INFO] [03/03/2012 22:28:51.625] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), KoPing(), OkPing(), Pong())

[INFO] [03/03/2012 22:28:51.706] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping(), KoPing(), OkPing(), Pong(), Ping())

[INFO] [03/03/2012 22:28:51.715] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), KoPing(), OkPing(), Pong(), Ping())

[INFO] [03/03/2012 22:28:52.68] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), KoPing(), OkPing(), Pong(), Ping(), Pong())

[INFO] [03/03/2012 22:28:52.86] ... [...pingPongTable]

Put: Vector()
Reg: Vector(OkPong(), KoPing(), OkPing(), Pong(), Ping(), Pong())

[INFO] [03/03/2012 22:28:52.142] ... [...pingPongTable]

Put: Vector()
Reg: Vector(OkPong(), KoPing(), Pong(), Ping(), Pong())

[INFO] [03/03/2012 22:28:52.161] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPing(), Pong(), Pong())



[info] Running akka.space.PongersApp
[INFO] [03/03/2012 22:28:39.19] [run-main] [ActorSystem(Pongers)]
REMOTE: RemoteServerStarted@akka://Pongers@127.0.0.1:2554
[INFO] [03/03/2012 22:28:39.184] ... [ActorSystem(Pongers)]
REMOTE: RemoteClientStarted@akka://PingPongTable@127.0.0.1:2552
[INFO] [03/03/2012 22:28:51.606] ... [...ponger_1] pong
[INFO] [03/03/2012 22:28:52.62] ... [...ponger_2] no pong
[INFO] [03/03/2012 22:28:52.72] ... [...pongers] ko
[INFO] [03/03/2012 22:28:52.80] ... [...pongers] pongers shutdown
[INFO] [03/03/2012 22:28:52.147] ... [ActorSystem(Pongers)]
REMOTE: RemoteClientShutdown@akka://PingPongTable@127.0.0.1:2552
[INFO] [03/03/2012 22:28:52.163] ... [ActorSystem(Pongers)]
REMOTE: RemoteServerShutdown@akka://Pongers@127.0.0.1:2554
[success] Total time: 17 s, completed Mar 3, 2012 10:28:52 PM
>



[info] Running akka.space.PingersApp
[INFO] [03/03/2012 22:28:50.689] [run-main] [ActorSystem(Pingers)]
REMOTE: RemoteServerStarted@akka://Pingers@127.0.0.1:2553
[INFO] [03/03/2012 22:28:50.807] ... [ActorSystem(Pingers)]
REMOTE: RemoteClientStarted@akka://PingPongTable@127.0.0.1:2552
[INFO] [03/03/2012 22:28:51.699] ... [...pinger_2] ping
[INFO] [03/03/2012 22:28:52.90] ... [.../pingers] ok
[INFO] [03/03/2012 22:28:52.90] ... [.../pingers] pingers shutdown
[INFO] [03/03/2012 22:28:52.146] ... [ActorSystem(Pingers)]
REMOTE: RemoteClientShutdown@akka://PingPongTable@127.0.0.1:2552
[INFO] [03/03/2012 22:28:52.167] ... [ActorSystem(Pingers)]
REMOTE: RemoteServerShutdown@akka://Pingers@127.0.0.1:2553
[success] Total time: 8 s, completed Mar 3, 2012 10:28:52 PM
>



Note: the actor ref space output is not shown.

Note: space output is one step behind reality (just run the pongers and the pingers again to realize that the pingpong table has been cleaned up).

Here is the space output after starting the pongers.




[INFO] [03/03/2012 22:32:16.137] [PingPongTable-13] [ActorSystem(PingPongTable)]
REMOTE: RemoteClientStarted@akka://Pongers@127.0.0.1:2554
[INFO] [03/03/2012 22:32:16.140] [PingPongTable-13] [ActorSystem(PingPongTable)]
REMOTE: RemoteClientShutdown@akka://Pongers@127.0.0.1:2554
[INFO] [03/03/2012 22:32:16.145] ... [...pingPongTable]

Put: Vector()
Reg: Vector()

[INFO] [03/03/2012 22:32:16.148] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong())

[INFO] [03/03/2012 22:32:16.153] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong())

[INFO] [03/03/2012 22:32:16.154] ... [...pingPongTable]

Put: Vector()
Reg: Vector(KoPong(), OkPong(), Ping())





StickTableApp


We are ready for a second application StickTableApp.






Stick


case class Stick(i: Int)



The case class Stick models the data that drive the application.






PingPongTable


case class StickTable(spaceSystem: ActorSystem, numberOfSticks: Int)
extends Space[Stick](spaceSystem) {
override def preStart() {
(1 to numberOfSticks) foreach { i =>
self ! Put(Stick(i))
}
}
}



The case class PingPongTable models the stick table.

Note: in the preStart of the stick table, the sticks are put on the stick table.






Hackers


case class Hackers(stickTableRef: ActorRef, numberOfSticks: Int)
extends Actor {
(1 to numberOfSticks) foreach { i =>
context.actorOf(
Props(Hakker(i,
numberOfSticks, stickTableRef,
4000, 4000, 5000, 8000)),
name = "hacker_" + i)
}

def receive: Receive = {
case _ =>
}
}

case class Hakker(
n: Int,
numberOfSticks: Int, stickTableRef: ActorRef,
startTime: Long, thinkTime: Long, eatTime: Long, delayTime: Long)
extends SpaceActor[Stick] {
val log = Logging(context.system, this)

private def next(n: Int) =
if (n == numberOfSticks) { 1 } else { n + 1 }

def takeLeftState() {
val left = n

pf = {
case l @ Stick(`left`) => {
log.info("has taken " + l)
takeRightState()
}
}

stickTableRef ! Reg(Stick(n))
}

def takeRightState() {
val right = next(n)

pf = {
case r @ Stick(`right`) => {
log.info("has taken " + r)
hack()
takeLeftState()
}
}

Thread.sleep(round(delayTime * random))

stickTableRef ! Reg(Stick(next(n)))
}

def hack() {
eat()
putBackSticks()
think()
}

private def eat() {
log.info("starts eating")
Thread.sleep(round(eatTime * random))
log.info("stops eating")
}

private def putBackSticks() {
val l = Stick(n)
log.info("puts back " + l)
stickTableRef ! Put(l)
val r = Stick(if (n == numberOfSticks) { 1 } else { n + 1 })
log.info("puts back " + r)
stickTableRef ! Put(r)
}

private def think() {
log.info("starts thinking")
Thread.sleep(round(thinkTime * random))
log.info("stops thinking")
}

def initialState() {
Thread.sleep(round(startTime * random))
takeLeftState()
}
}




A hackers supervisor creates hackers.

A hacker starts in its take left state taking the Stick left to and transitioning to its take right state taking the Stick right to it.


When he has taken both sticks, he starts eating, puts back the sticks, thinks for a moment, and transitions back to its take left state.






StickTableApp


class StickTableApplication extends Bootable {
val stickTableSystem = ActorSystem(
"StickTable",
ConfigFactory.load.getConfig("stickTable"))

val numberOfSticks = 5

val stickTableRef = stickTableSystem.actorOf(
Props(StickTable(stickTableSystem, numberOfSticks)),
name = "stickTable")

def startup() {
}

def shutdown() {
stickTableSystem.shutdown()
}
}

object StickTableApp {
df main(args: Array[String]) = {
val application = new StickTableApplication
}
}



The stick table app simply installs a stick table.






PingersApp and PongersApp


class HackersApplication extends Bootable {
val hackersSystem = ActorSystem(
"Hackers",
ConfigFactory.load.getConfig("hackers"))

val stickTableRef = hackersSystem.actorFor(
"akka://StickTable@127.0.0.1:2555/user/stickTable")

val numberOfSticks = 5

val hackersRef = hackersSystem.actorOf(
Props(Hackers(stickTableRef, numberOfSticks)),
name = "hackers")

def startup() {
}

def shutdown() {
hackersSystem.shutdown()
}
}

object HackersApp {
def main(args: Array[String]) = {
val application = new HackersApplication
}
}



The hackers app simply looks up a stick table and installs a hackers supervisor.






Configuration


//# application.conf
stickTable {
include "common"

akka {
remote.netty.port = 2555
}
}

hackers {
include "common"

akka {
remote.netty.port = 2556
}
}





Running the HackersApp and StickTableApp


Running the apps produces something like below (in this case an immediate deadlock).




[info] Running akka.space.StickTableApp
[INFO] [03/03/2012 23:03:55.699] [run-main] [ActorSystem(StickTable)]
REMOTE: RemoteServerStarted@akka://StickTable@127.0.0.1:2555
[INFO] [03/03/2012 23:03:55.810] ... [...stickTable]

Put: Vector()
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:03:55.835] ... [...stickTable]

Put: Vector(Stick(1))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:03:55.836] ... [...stickTable]

Put: Vector(Stick(1), Stick(2))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:03:55.837] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:03:55.842] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:14.951] [StickTable-6] [ActorSystem(StickTable)]
REMOTE: RemoteClientStarted@akka://Hackers@127.0.0.1:2556
[INFO] [03/03/2012 23:04:14.966] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3), Stick(4), Stick(5))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:15.415] ... [...stickTable]

Put: Vector(Stick(1), Stick(3), Stick(4), Stick(5))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:16.224] ... [...stickTable]

Put: Vector(Stick(1), Stick(3), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:16.807] ... [...stickTable]

Put: Vector(Stick(1), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:16.849] ... [...stickTable]

Put: Vector(Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:17.821] ... [...stickTable]

Put: Vector()
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/03/2012 23:04:19.748] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4))
Reg (actor refs): Vector(...hacker_3)

[INFO] [03/03/2012 23:04:20.360] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4), Stick(2))
Reg (actor refs): Vector(...hacker_3, ...hacker_1)

[INFO] [03/03/2012 23:04:21.884] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4), Stick(2), Stick(3))
Reg (actor refs): Vector(...hacker_3, ...hacker_1, ...hacker_2)

[INFO] [03/03/2012 23:04:24.842] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4), Stick(2), Stick(3), Stick(1))
Reg (actor refs): Vector(...hacker_3, ...hacker_1, ...hacker_2, ...hacker_5)


[info] Running akka.space.HackersApp
[INFO] [03/03/2012 23:04:14.263] [run-main] [ActorSystem(Hackers)]
REMOTE: RemoteServerStarted@akka://Hackers@127.0.0.1:2556
[INFO] [03/03/2012 23:04:14.912] ... [ActorSystem(Hackers)]
REMOTE: RemoteClientStarted@akka://StickTable@127.0.0.1:2555
[INFO] [03/03/2012 23:04:14.992] ... [...hacker_2] has taken Stick(2)
[INFO] [03/03/2012 23:04:15.418] ... [...hacker_5] has taken Stick(5)
[INFO] [03/03/2012 23:04:16.226] ... [...hacker_3] has taken Stick(3)
[INFO] [03/03/2012 23:04:16.809] ... [...hacker_1] has taken Stick(1)
[INFO] [03/03/2012 23:04:16.853] ... [...hacker_4] has taken Stick(4)






Running the apps may also produce something like below (in this case no deadlock (yet)).




[info] Running akka.space.StickTableApp
[INFO] [03/04/2012 17:14:28.520] [run-main] [ActorSystem(StickTable)]
REMOTE: RemoteServerStarted@akka://StickTable@127.0.0.1:2555
[INFO] [03/04/2012 17:14:28.633] ... [...stickTable]

Put: Vector()
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:28.650] ... [...stickTable]

Put: Vector(Stick(1))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:28.651] ... [...stickTable]

Put: Vector(Stick(1), Stick(2))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:28.653] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:28.655] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:39.585] [StickTable-7] [ActorSystem(StickTable)]
REMOTE: RemoteClientStarted@akka://Hackers@127.0.0.1:2556
[INFO] [03/04/2012 17:14:39.596] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3), Stick(4), Stick(5))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:39.690] ... [...stickTable]

Put: Vector(Stick(1), Stick(2), Stick(3), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:40.145] ... [...stickTable]

Put: Vector(Stick(2), Stick(3), Stick(4))
Reg: Vector()
Reg (actor refs): Vector()

[INFO] [03/04/2012 17:14:40.803] ... [...stickTable]

Put: Vector(Stick(2), Stick(3), Stick(4))
Reg: Vector(Stick(1))
Reg (actor refs): Vector(...hacker_1)

[INFO] [03/04/2012 17:14:40.830] ... [...stickTable]

Put: Vector(Stick(3), Stick(4))
Reg: Vector(Stick(1))
Reg (actor refs): Vector(...hacker_1)

[INFO] [03/04/2012 17:14:41.957] ... [...stickTable]

Put: Vector(Stick(4))
Reg: Vector(Stick(1))
Reg (actor refs): Vector(...hacker_1)

[INFO] [03/04/2012 17:14:42.94] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(1))
Reg (actor refs): Vector(...hacker_1)

[INFO] [03/04/2012 17:14:42.114] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(1), Stick(3))
Reg (actor refs): Vector(...hacker_1, ...hacker_3)

[INFO] [03/04/2012 17:14:43.466] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(1), Stick(3), Stick(5))
Reg (actor refs): Vector(...hacker_1, ...hacker_3, ...hacker_4)

[INFO] [03/04/2012 17:14:43.470] ... [...stickTable]

Put: Vector(Stick(2))
Reg: Vector(Stick(1), Stick(3), Stick(5))
Reg (actor refs): Vector(...hacker_1, ...hacker_3, ...hacker_4)

[INFO] [03/04/2012 17:14:43.710] ... [...stickTable]

Put: Vector(Stick(2))
Reg: Vector(Stick(1), Stick(5))
Reg (actor refs): Vector(...hacker_1, ...hacker_4)

[INFO] [03/04/2012 17:14:44.443] ... [...stickTable]

Put: Vector(Stick(2))
Reg: Vector(Stick(1), Stick(5), Stick(4))
Reg (actor refs): Vector(...hacker_1, ...hacker_4, ...hacker_3)

[INFO] [03/04/2012 17:14:44.447] ... [...stickTable]

Put: Vector(Stick(2))
Reg: Vector(Stick(1), Stick(4))
Reg (actor refs): Vector(...hacker_1, ...hacker_3)

[INFO] [03/04/2012 17:14:44.458] ... [...stickTable]

Put: Vector(Stick(2))
Reg: Vector(Stick(4))
Reg (actor refs): Vector(...hacker_3)

[INFO] [03/04/2012 17:14:44.574] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4))
Reg (actor refs): Vector(...hacker_3)

[INFO] [03/04/2012 17:14:45.82] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4), Stick(3))
Reg (actor refs): Vector(...hacker_3, ...hacker_2)

[INFO] [03/04/2012 17:14:45.423] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(4), Stick(3), Stick(2))
Reg (actor refs): Vector(...hacker_3, ...hacker_2, ...hacker_1)

[INFO] [03/04/2012 17:14:45.426] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(3), Stick(2))
Reg (actor refs): Vector(...hacker_2, ...hacker_1)

[INFO] [03/04/2012 17:14:46.805] ... [...stickTable]

Put: Vector(Stick(5))
Reg: Vector(Stick(3), Stick(2))
Reg (actor refs): Vector(...hacker_2, ...hacker_1)

[INFO] [03/04/2012 17:14:47.750] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(3), Stick(2))
Reg (actor refs): Vector(...hacker_2, ...hacker_1)

[INFO] [03/04/2012 17:14:47.908] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(3), Stick(2), Stick(1))
Reg (actor refs): Vector(...hacker_2, ...hacker_1, ...hacker_5)

[INFO] [03/04/2012 17:14:50.216] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(3), Stick(2), Stick(1), Stick(4))
Reg (actor refs): Vector(...hacker_2, ...hacker_1, ...hacker_5, ...hacker_4)

[INFO] [03/04/2012 17:14:50.220] ... [...stickTable]

Put: Vector()
Reg: Vector(Stick(2), Stick(1), Stick(4))
Reg (actor refs): Vector(...hacker_1, ...hacker_5, ...hacker_4)



[info] Running akka.space.HackersApp
[INFO] [03/04/2012 17:14:38.303] [run-main] [ActorSystem(Hackers)]
REMOTE: RemoteServerStarted@akka://Hackers@127.0.0.1:2556
[INFO] [03/04/2012 17:14:39.528] ... [ActorSystem(Hackers)]
REMOTE: RemoteClientStarted@akka://StickTable@127.0.0.1:2555
[INFO] [03/04/2012 17:14:39.631] ... [...hacker_5] has taken Stick(5)
[INFO] [03/04/2012 17:14:39.694] ... [...hacker_5] has taken Stick(1)
[INFO] [03/04/2012 17:14:39.694] ... [...hacker_5] starts eating
[INFO] [03/04/2012 17:14:40.807] ... [...hacker_2] has taken Stick(2)
[INFO] [03/04/2012 17:14:40.831] ... [...hacker_2] has taken Stick(3)
[INFO] [03/04/2012 17:14:40.832] ... [...hacker_2] starts eating
[INFO] [03/04/2012 17:14:41.960] ... [...hacker_4] has taken Stick(4)
[INFO] [03/04/2012 17:14:43.453] ... [...hacker_2] stops eating
[INFO] [03/04/2012 17:14:43.453] ... [...hacker_2] puts back Stick(2)
[INFO] [03/04/2012 17:14:43.458] ... [...hacker_2] puts back Stick(3)
[INFO] [03/04/2012 17:14:43.462] ... [...hacker_2] starts thinking
[INFO] [03/04/2012 17:14:43.473] ... [...hacker_3] has taken Stick(3)
[INFO] [03/04/2012 17:14:44.436] ... [...hacker_5] stops eating
[INFO] [03/04/2012 17:14:44.437] ... [...hacker_5] puts back Stick(5)
[INFO] [03/04/2012 17:14:44.439] ... [...hacker_5] puts back Stick(1)
[INFO] [03/04/2012 17:14:44.440] ... [...hacker_5] starts thinking
[INFO] [03/04/2012 17:14:44.446] ... [...hacker_4] has taken Stick(5)
[INFO] [03/04/2012 17:14:44.446] ... [...hacker_4] starts eating
[INFO] [03/04/2012 17:14:44.448] ... [...hacker_2] stops thinking
[INFO] [03/04/2012 17:14:44.456] ... [...hacker_1] has taken Stick(1)
[INFO] [03/04/2012 17:14:44.459] ... [...hacker_2] has taken Stick(2)
[INFO] [03/04/2012 17:14:45.417] ... [...hacker_4] stops eating
[INFO] [03/04/2012 17:14:45.418] ... [...hacker_4] puts back Stick(4)
[INFO] [03/04/2012 17:14:45.419] ... [...hacker_4] puts back Stick(5)
[INFO] [03/04/2012 17:14:45.420] ... [...hacker_4] starts thinking
[INFO] [03/04/2012 17:14:45.426] ... [...hacker_3] has taken Stick(4)
[INFO] [03/04/2012 17:14:45.426] ... [...hacker_3] starts eating
[INFO] [03/04/2012 17:14:46.800] ... [...hacker_5] stops thinking
[INFO] [03/04/2012 17:14:46.808] ... [...hacker_5] has taken Stick(5)
[INFO] [03/04/2012 17:14:47.903] ... [...hacker_4] stops thinking
[INFO] [03/04/2012 17:14:50.210] ... [...hacker_3] stops eating
[INFO] [03/04/2012 17:14:50.211] ... [...hacker_3] puts back Stick(3)
[INFO] [03/04/2012 17:14:50.214] ... [...hacker_3] puts back Stick(4)
[INFO] [03/04/2012 17:14:50.215] ... [...hacker_3] starts thinking
[INFO] [03/04/2012 17:14:50.219] ... [...hacker_2] has taken Stick(3)
[INFO] [03/04/2012 17:14:50.220] ... [...hacker_2] starts eating
[INFO] [03/04/2012 17:14:50.223] ... [...hacker_4] has taken Stick(4)



Note: at [03/04/2012 17:14:40.832] both hacker_5 and hacker_2
are eating.

Note: the situation of the table around that time is


[INFO] [03/04/2012 17:14:41.957] ... [...stickTable]

Put: Vector(Stick(4))
Reg: Vector(Stick(1))
Reg (actor refs): Vector(...hacker_1)

Stick(4) is on the stick table and and hacker_1 is waiting for Stick(1).

No comments:

Post a Comment