Skip to content

Instantly share code, notes, and snippets.

@dholbrook
Created October 12, 2011 03:03
Show Gist options
  • Save dholbrook/1280150 to your computer and use it in GitHub Desktop.
Save dholbrook/1280150 to your computer and use it in GitHub Desktop.
Sleeping Barber Problem, Akka actor implementation
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