import akka.actor.Actor import akka.actor.ActorRef import akka.actor.Props import akka.util.duration._ import scala.actors.threadpool.TimeUnit import akka.actor.ActorSystem sealed trait TableMessage case class Take(philosopher: ActorRef) extends TableMessage case class Taken(fork: ActorRef) extends TableMessage object Eat extends TableMessage object Think extends TableMessage object Busy extends TableMessage object Put extends TableMessage class Fork extends Actor { import context.become def available: Receive = { case Take(philosopher) => become(taken) philosopher ! Taken(self) } def taken: Receive = { case Take(otherOne) => otherOne ! Busy case Put => become(available) case x => println(x) } def receive = available } class Philosopher(left: ActorRef, right: ActorRef) extends Actor { import context.become import context.system def hungry: Receive = { case Taken(this.left) => become(waiting_for(right, left)) case Taken(this.right) => become(waiting_for(left, right)) case Busy => become(denied) } def eating: Receive = { case Think => println(self.path.name + " puts down his forks and starts to think") become(thinking) left ! Put right ! Put system.scheduler.scheduleOnce(3 seconds, self, Eat) } def waiting_for(toWaitFor: ActorRef, taken: ActorRef): Receive = { case Taken(toWaitFor) => become(eating) println(self.path.name + " has taken " + taken.path.name + " and " + toWaitFor.path.name) system.scheduler.scheduleOnce(3 seconds, self, Think) case Busy => become(thinking) taken ! Put self ! Eat } def thinking: Receive = { case Eat => become(hungry) left ! Take(self) right ! Take(self) } def denied: Receive = { case Taken(fork) => become(thinking) fork ! Put self ! Eat case Busy => become(thinking) self ! Eat } def receive = { case Think => become(thinking) system.scheduler.scheduleOnce(1 seconds, self, Eat) } } object Dining extends App { val system = ActorSystem("DiningTable") val forks = for (i <- 1 to 5) yield system.actorOf(Props[Fork], "fork" + i) val philosophers = for { (name, i) <- (List("Pluto", "Socrates", "Aristotle", "Pythagoras", "Zeno").zipWithIndex) } yield system.actorOf(Props(new Philosopher(forks(i), forks((i + 1) % 5))), name) philosophers.foreach(_ ! Think) }