Created
October 12, 2011 03:03
-
-
Save dholbrook/1280150 to your computer and use it in GitHub Desktop.
Sleeping Barber Problem, Akka actor implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.Thread | |
import scala.collection.mutable.Queue | |
import akka.actor.Uuid | |
import akka.actor.scala2ActorRef | |
import akka.actor.Actor | |
import akka.event.EventHandler | |
/* | |
* Sleeping Barber Code Club Problem | |
* See (http://en.wikipedia.org/wiki/Sleeping_barber_problem) | |
* | |
* Note: could use _significant_ clean-up. | |
* :-) | |
* | |
* D. Holbrook | |
*/ | |
//Messages | |
sealed trait EventMessage | |
case class RegisterBarber(uuid: Uuid) | |
case class RegisterBarberShop(uuid: Uuid) | |
case class CustomerWalkIn(uuid: Uuid) extends EventMessage | |
case class InShop extends EventMessage | |
case class InBarberChair extends EventMessage | |
case class WaitingRoomFull extends EventMessage | |
case class InWaitingRoom extends EventMessage | |
case class LeavesWaitingRoom extends EventMessage | |
case class ExitsShop extends EventMessage | |
case class CutHair extends EventMessage | |
case class HairCutDone extends EventMessage | |
class Customer(customerName: String) extends Actor { | |
def receive = { | |
case InShop => EventHandler.info(this, customerName + " Now In Shop") | |
case InBarberChair => EventHandler.info(this, customerName + " In Barber Chair") | |
case WaitingRoomFull => EventHandler.info(this, customerName + " Waiting Room Full - Leaving") | |
case InWaitingRoom => EventHandler.info(this, customerName + " Sits In Waiting Room") | |
case LeavesWaitingRoom => EventHandler.info(this, customerName + " Leaves Waiting Room") | |
case ExitsShop => { | |
EventHandler.info(this, customerName + " Exits Shop") | |
self.stop | |
} | |
case _ => EventHandler.info(this, "received unknown message ") | |
} | |
} | |
class BarberShop(waitingRoomChairCount: Int) extends Actor { | |
private var barberUuid: Option[Uuid] = None | |
private var waitingRoom = Queue[Uuid]() | |
private var barberChair: Option[Uuid] = None | |
def barber = for { | |
uuid <- barberUuid; | |
actor <- Actor.registry.actorFor(uuid) | |
} yield actor | |
def receive = { | |
case RegisterBarber(uuid) => barberUuid = Some(uuid) | |
case CustomerWalkIn(c) => customerWalksIn(c) | |
case HairCutDone => hairCutDone | |
case _ => EventHandler.info(this, "received unknown message") | |
} | |
private def customerWalksIn(customerUuid: Uuid) { | |
val customer = Actor.registry.actorFor(customerUuid) | |
barberChair match { | |
case None => customerToBarberChair(customerUuid) | |
case _ => customerToWaitingRoom(customerUuid) | |
} | |
} | |
private def hairCutDone = { | |
for (customerUuid <- barberChair) customerLeavesBarberChair(customerUuid) | |
barberChair = nextCustomerFromWaitingRoom() | |
for (customerUuid <- barberChair) customerToBarberChair(customerUuid) | |
} | |
private def customerToBarberChair(customerUuid: Uuid) { | |
val customer = Actor.registry.actorFor(customerUuid) | |
barberChair = Some(customerUuid) | |
customer ! InBarberChair | |
barber ! CutHair | |
} | |
private def customerLeavesBarberChair(customerUuid: Uuid) { | |
val customer = Actor.registry.actorFor(customerUuid) | |
barberChair = None | |
customer ! ExitsShop | |
} | |
private def customerToWaitingRoom(customerUuid: Uuid) { | |
val customer = Actor.registry.actorFor(customerUuid) | |
if (waitingRoom.size < waitingRoomChairCount) { | |
waitingRoom.enqueue(customerUuid) | |
customer ! InWaitingRoom | |
} else { | |
customer ! WaitingRoomFull | |
customer ! ExitsShop | |
} | |
} | |
private def nextCustomerFromWaitingRoom(): Option[Uuid] = { | |
val nextCustomerUuid = | |
if (waitingRoom.isEmpty) None | |
else Some(waitingRoom.dequeue()) | |
for ( | |
uuid <- nextCustomerUuid; | |
customer <- Actor.registry.actorFor(uuid) | |
) { | |
customer ! LeavesWaitingRoom | |
} | |
nextCustomerUuid | |
} | |
} | |
//Barber Actor | |
class Barber() extends Actor { | |
private var barberShopUuid: Option[Uuid] = None | |
def barberShop = for { | |
id <- barberShopUuid; | |
ar <- Actor.registry.actorFor(id) | |
} yield ar | |
def receive = { | |
case RegisterBarberShop(uuid) => barberShopUuid = Some(uuid) | |
case CutHair => cutHair | |
case _ => EventHandler.info(this, "received unknown message") | |
} | |
def cutHair = { | |
EventHandler.info(this, "Cutting Hair - Started") | |
Thread.sleep(1000) | |
EventHandler.info(this, "Cutting Hair - Done") | |
barberShop ! HairCutDone | |
} | |
} | |
object SleepingBarber extends App { | |
val shop = Actor.actorOf(new BarberShop(2)).start | |
val barber = Actor.actorOf[Barber].start | |
barber ! RegisterBarberShop(shop.getUuid()) | |
shop ! RegisterBarber(barber.getUuid()) | |
for (i <- 1 to 10) { | |
val c = Actor.actorOf(new Customer("cust" + i)).start | |
shop ! CustomerWalkIn(c.getUuid()) | |
Thread.sleep(500) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment