eengbrec / Scala Enhancements
In-progress enhancements to the Scala standard library, mostly centered around actors.
Clone this repository (size: 130.0 MB): HTTPS / SSH
$ hg clone http://bitbucket.org/eengbrec/scala-enhancements/
| commit 82: | 14e33a6ea1f8 |
| parent 70: | 2af7041fc9f9 |
| branch: | message_queue_patch |
message queue patch
9 months ago
| r82:14e33a6ea1f8 | 148 loc | 4.5 KB | embed / history / annotate / raw / |
|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2005-2009, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
// $Id: MessageQueue.scala 16893 2009-01-13 13:09:22Z cunei $
package scala.actors
import scala.reflect.Manifest
trait MessageQueue[MsgType <: Message[_]] {
def isEmpty: Boolean
def size: Int
def append(message: MsgType): Unit
def foldLeft[B](z: B )(f: (B, Any) => B): B
/**
* get the nth message matching p from the queue
* The matching message is NOT removed from the queue
* @param n the number of matching messages to skip before returning a result
* @param p predicate used to match a message
* @return Some(msg) if a matching message is found, otherwise None
*/
def get(n: Int)(p: MsgType => Boolean): Option[MsgType]
/**
* remove the nth message matching p from the queue and return it
* @param n the number of matching messages to skip before returning a result
* @param p the predicate used to match a message
* @return Some(msg) if a matching message is found, otherwise None
*/
def remove(n: Int)(p: MsgType => Boolean): Option[MsgType]
/**
* remove and return the first message matching p
* equivalent to get(0)(p)
* @param p the predicate used to match a message
* @return Some(msg) is a matching message is found, otherwise None
*/
def extractFirst(p: MsgType => Boolean): Option[MsgType]
}
/**
* The class <code>MessageQueue</code> provides an efficient
* implementation of a message queue specialized for this actor
* library.
*
* @version 0.9.9
* @author Philipp Haller
*/
@serializable
class BasicMessageQueue[MsgType <: Message[_]] extends MessageQueue[MsgType] {
@serializable
protected class Element(val message: MsgType, var next: Element) {
def this(message: MsgType) = this(message, null)
}
private var first: Element = null
/**
* The last element in the queue
* This is used so that the append operation can be constant time.
* last == null iff queue is empty
*/
private var last: Element = null
def isEmpty = null eq last
private var _size = 0
def size = _size
protected def changeSize(diff: Int) = {
_size += diff
}
def append(message: MsgType): Unit = {
changeSize(1) // size always increases by 1
if (null eq last) { // list empty
val el = new Element(message)
first = el
last = el
} else {
val el = new Element(message)
last.next = el
last = el
}
}
def foldLeft[B](z: B)(f: (B, Any) => B): B = {
var acc = z
var curr = first
while (curr != null) {
acc = f(acc, curr.message)
curr = curr.next
}
acc
}
/** Returns the n-th msg that satisfies the predicate
* without removing it.
*/
def get(n: Int)(p: MsgType => Boolean) = findMessage(n, p, false)
/** Removes the n-th msg that satisfies the predicate.
*/
def remove(n: Int)(p: MsgType => Boolean) = findMessage(n, p, true)
/**
* Find the nth element with a mssage matching p and return it
* @param n the number of matching messages to skip before returning
* @param p predicate used to test messages
* @param remove set to true if the message should be removed from the queue before
* being returned, false if it should be left in the queue
* @return Some(msg) if a matching message is found, otherwise None
*/
def findMessage(n: Int, p: MsgType => Boolean, remove: Boolean) = {
def f(n: Int, prev: Element, cur: Element): Option[MsgType] = {
if (cur eq null) None
else if (p(cur.message)) {
if (n > 0) f(n - 1, cur, cur.next)
else {
if (remove) removeElement(prev, cur)
Some(cur.message)
}
} else f(n, cur, cur.next)
}
f(n, null, first)
}
protected def removeElement(prev: Element, cur: Element): Unit = {
if (prev eq null) {
first = cur.next // removing the first element
} else {
prev.next = cur.next
}
if (cur eq last) {
last = prev // removing the last element
if (last eq null) first = null // queue is now empty
}
changeSize(-1)
}
def extractFirst(p: MsgType => Boolean) = findMessage(0, p, true)
}
|
