HW 7 done
This commit is contained in:
parent
a32975e772
commit
3c60eb0a1b
@ -58,7 +58,7 @@ class BinaryTreeSet extends Actor {
|
||||
|
||||
var root = createRoot
|
||||
|
||||
// optional (used to stash incoming operations during garbage collection)
|
||||
// optional
|
||||
var pendingQueue = Queue.empty[Operation]
|
||||
|
||||
// optional
|
||||
@ -66,15 +66,30 @@ class BinaryTreeSet extends Actor {
|
||||
|
||||
// optional
|
||||
/** Accepts `Operation` and `GC` messages. */
|
||||
val normal: Receive = { case _ => ??? }
|
||||
val normal: Receive = {
|
||||
case op:Operation => root ! op
|
||||
case GC => {
|
||||
val newRoot = createRoot;
|
||||
root ! CopyTo(newRoot)
|
||||
context.become(garbageCollecting(newRoot))
|
||||
}
|
||||
}
|
||||
|
||||
// optional
|
||||
/** Handles messages while garbage collection is performed.
|
||||
* `newRoot` is the root of the new binary tree where we want to copy
|
||||
* all non-removed elements into.
|
||||
*/
|
||||
def garbageCollecting(newRoot: ActorRef): Receive = ???
|
||||
|
||||
def garbageCollecting(newRoot: ActorRef): Receive = {
|
||||
case op:Operation => pendingQueue = pendingQueue.enqueue(op)
|
||||
case CopyFinished =>
|
||||
pendingQueue.foreach(newRoot ! _) //foreach preserves order of a queue (same as dequeueing)
|
||||
root ! PoisonPill //Will also stop all of its children
|
||||
pendingQueue = Queue.empty
|
||||
root = newRoot;
|
||||
context.become(normal)
|
||||
//Ignore GC messages here
|
||||
}
|
||||
}
|
||||
|
||||
object BinaryTreeNode {
|
||||
@ -84,11 +99,6 @@ object BinaryTreeNode {
|
||||
case object Right extends Position
|
||||
|
||||
case class CopyTo(treeNode: ActorRef)
|
||||
/**
|
||||
* Acknowledges that a copy has been completed. This message should be sent
|
||||
* from a node to its parent, when this node and all its children nodes have
|
||||
* finished being copied.
|
||||
*/
|
||||
case object CopyFinished
|
||||
|
||||
def props(elem: Int, initiallyRemoved: Boolean) = Props(classOf[BinaryTreeNode], elem, initiallyRemoved)
|
||||
@ -104,15 +114,76 @@ class BinaryTreeNode(val elem: Int, initiallyRemoved: Boolean) extends Actor {
|
||||
// optional
|
||||
def receive = normal
|
||||
|
||||
def goDownTo(elem : Int) : Position = if(elem < this.elem) Left else Right
|
||||
// optional
|
||||
/** Handles `Operation` messages and `CopyTo` requests. */
|
||||
val normal: Receive = { case _ => ??? }
|
||||
val normal: Receive = {
|
||||
case Insert (requester, id, elem) =>
|
||||
if(elem == this.elem && !removed){
|
||||
requester ! OperationFinished(id)
|
||||
}else{
|
||||
val nextPos = goDownTo(elem)
|
||||
|
||||
subtrees get nextPos match{
|
||||
case Some(node) => node ! Insert(requester, id, elem)
|
||||
case None => {
|
||||
val newActorSubtree = (nextPos, context.actorOf(BinaryTreeNode.props(elem, false)))
|
||||
subtrees = subtrees + newActorSubtree
|
||||
requester ! OperationFinished(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
case Contains(requester, id, elem) =>
|
||||
if(elem == this.elem && !removed)
|
||||
requester ! ContainsResult(id, true)
|
||||
else{
|
||||
//Need to search subtrees
|
||||
subtrees get goDownTo(elem) match{
|
||||
case Some(node) => node ! Contains(requester, id, elem)
|
||||
case None => requester ! ContainsResult(id, false)
|
||||
}
|
||||
}
|
||||
|
||||
case Remove (requester, id, elem) =>
|
||||
if(elem == this.elem && !removed){
|
||||
removed = true
|
||||
requester ! OperationFinished(id)
|
||||
}else{
|
||||
subtrees get goDownTo(elem) match{
|
||||
case Some(node) => node ! Remove(requester, id, elem)
|
||||
case None => requester ! OperationFinished(id) // (elem isn't in the tree)
|
||||
}
|
||||
}
|
||||
|
||||
case CopyTo(newRoot) =>
|
||||
//We are already done, nothing to do
|
||||
if(removed && subtrees.isEmpty) context.parent ! CopyFinished
|
||||
else{
|
||||
if(!removed) newRoot ! Insert(self, elem, elem)
|
||||
subtrees.values foreach(_ ! CopyTo(newRoot)) //Copy subtrees elems
|
||||
//val insertConfirmed = if(removed) true else false, hence we can simply pass removed
|
||||
context.become(copying(subtrees.values.toSet, removed))
|
||||
}
|
||||
}
|
||||
|
||||
// optional
|
||||
/** `expected` is the set of ActorRefs whose replies we are waiting for,
|
||||
* `insertConfirmed` tracks whether the copy of this node to the new tree has been confirmed.
|
||||
*/
|
||||
def copying(expected: Set[ActorRef], insertConfirmed: Boolean): Receive = ???
|
||||
|
||||
|
||||
}
|
||||
def copying(expected: Set[ActorRef], insertConfirmed: Boolean): Receive = {
|
||||
//To catch the insert of this node into the new tree beeing finished
|
||||
case OperationFinished(_) => {
|
||||
if(expected.isEmpty) context.parent ! CopyFinished
|
||||
else context.become(copying(expected, true))
|
||||
}
|
||||
|
||||
case CopyFinished => {
|
||||
val newExp = expected-sender
|
||||
if(insertConfirmed && newExp.isEmpty){
|
||||
context.parent ! CopyFinished
|
||||
}else{
|
||||
context.become(copying(newExp, insertConfirmed))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user