package scala.collection
package parallel.mutable
import collection.mutable.HashEntry
import collection.parallel.IterableSplitter
trait ParHashTable[K, Entry >: Null <: HashEntry[K, Entry]] extends collection.mutable.HashTable[K, Entry] {
override def alwaysInitSizeMap = true
abstract class EntryIterator[T, +IterRepr <: IterableSplitter[T]]
(private var idx: Int, private val until: Int, private val totalsize: Int, private var es: Entry)
extends IterableSplitter[T] with SizeMapUtils {
private val itertable = table
private var traversed = 0
scan()
def entry2item(e: Entry): T
def newIterator(idxFrom: Int, idxUntil: Int, totalSize: Int, es: Entry): IterRepr
def hasNext = {
es ne null
}
def next: T = {
val res = es
es = es.next
scan()
traversed += 1
entry2item(res)
}
def scan() {
while (es == null && idx < until) {
es = itertable(idx).asInstanceOf[Entry]
idx = idx + 1
}
}
def remaining = totalsize - traversed
private[parallel] override def debugInformation = {
buildString {
append =>
append("/--------------------\\")
append("Parallel hash table entry iterator")
append("total hash table elements: " + tableSize)
append("pos: " + idx)
append("until: " + until)
append("traversed: " + traversed)
append("totalsize: " + totalsize)
append("current entry: " + es)
append("underlying from " + idx + " until " + until)
append(itertable.slice(idx, until).map(x => if (x != null) x.toString else "n/a").mkString(" | "))
append("\\--------------------/")
}
}
def dup = newIterator(idx, until, totalsize, es)
def split: Seq[IterableSplitter[T]] = if (remaining > 1) {
if (until > idx) {
val divsz = (until - idx) / 2
val sidx = idx + divsz + 1
val suntil = until
val ses = itertable(sidx - 1).asInstanceOf[Entry]
val stotal = calcNumElems(sidx - 1, suntil, table.length, sizeMapBucketSize)
val fidx = idx
val funtil = idx + divsz
val fes = es
val ftotal = totalsize - stotal
Seq(
newIterator(fidx, funtil, ftotal, fes),
newIterator(sidx, suntil, stotal, ses)
)
} else {
val arr = convertToArrayBuffer(es)
val arrpit = new collection.parallel.BufferSplitter[T](arr, 0, arr.length, signalDelegate)
arrpit.split
}
} else Seq(this.asInstanceOf[IterRepr])
private def convertToArrayBuffer(chainhead: Entry): mutable.ArrayBuffer[T] = {
var buff = mutable.ArrayBuffer[Entry]()
var curr = chainhead
while (curr ne null) {
buff += curr
curr = curr.next
}
buff map { e => entry2item(e) }
}
protected def countElems(from: Int, until: Int) = {
var c = 0
var idx = from
var es: Entry = null
while (idx < until) {
es = itertable(idx).asInstanceOf[Entry]
while (es ne null) {
c += 1
es = es.next
}
idx += 1
}
c
}
protected def countBucketSizes(fromBucket: Int, untilBucket: Int) = {
var c = 0
var idx = fromBucket
while (idx < untilBucket) {
c += sizemap(idx)
idx += 1
}
c
}
}
}