HW 7 done
This commit is contained in:
parent
a32975e772
commit
3c60eb0a1b
@ -58,7 +58,7 @@ class BinaryTreeSet extends Actor {
|
|||||||
|
|
||||||
var root = createRoot
|
var root = createRoot
|
||||||
|
|
||||||
// optional (used to stash incoming operations during garbage collection)
|
// optional
|
||||||
var pendingQueue = Queue.empty[Operation]
|
var pendingQueue = Queue.empty[Operation]
|
||||||
|
|
||||||
// optional
|
// optional
|
||||||
@ -66,15 +66,30 @@ class BinaryTreeSet extends Actor {
|
|||||||
|
|
||||||
// optional
|
// optional
|
||||||
/** Accepts `Operation` and `GC` messages. */
|
/** 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
|
// optional
|
||||||
/** Handles messages while garbage collection is performed.
|
/** Handles messages while garbage collection is performed.
|
||||||
* `newRoot` is the root of the new binary tree where we want to copy
|
* `newRoot` is the root of the new binary tree where we want to copy
|
||||||
* all non-removed elements into.
|
* 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 {
|
object BinaryTreeNode {
|
||||||
@ -84,11 +99,6 @@ object BinaryTreeNode {
|
|||||||
case object Right extends Position
|
case object Right extends Position
|
||||||
|
|
||||||
case class CopyTo(treeNode: ActorRef)
|
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
|
case object CopyFinished
|
||||||
|
|
||||||
def props(elem: Int, initiallyRemoved: Boolean) = Props(classOf[BinaryTreeNode], elem, initiallyRemoved)
|
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
|
// optional
|
||||||
def receive = normal
|
def receive = normal
|
||||||
|
|
||||||
|
def goDownTo(elem : Int) : Position = if(elem < this.elem) Left else Right
|
||||||
// optional
|
// optional
|
||||||
/** Handles `Operation` messages and `CopyTo` requests. */
|
/** 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
|
// optional
|
||||||
/** `expected` is the set of ActorRefs whose replies we are waiting for,
|
/** `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.
|
* `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