All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.reactors.common.UnrolledBuffer.scala Maven / Gradle / Ivy

package io.reactors
package common



import scala.annotation.tailrec



class UnrolledBuffer[@specialized(Int, Long, Double) T](
  implicit val arrayable: Arrayable[T]
) {
  import UnrolledBuffer._

  private[reactors] var start: Node[T] = _
    
  private[reactors] var rawEnd: Node[T] = _

  def end: Node[T] = rawEnd

  def end_=(n: Node[T]) = rawEnd = n

  def init(self: UnrolledBuffer[T]) {
    start = new Node[T](this, arrayable.newRawArray(INITIAL_NODE_LENGTH))
    end = start
  }

  init(this)

  def isEmpty = !nonEmpty

  @tailrec private def advance() {
    if (start.startIndex >= start.endIndex) {
      if (start.next != null) {
        val old = start
        start = start.next
        old.next = null
        advance()
      }
    }
  }

  def nonEmpty = {
    advance()
    start.startIndex < start.endIndex
  }

  def head: T = {
    if (nonEmpty) start.array(start.startIndex)
    else throw new NoSuchElementException("empty")
  }

  def dequeue(): T = {
    if (isEmpty) throw new NoSuchElementException("empty")
    val array = start.array
    val si = start.startIndex
    val elem = array(si)
    array(si) = arrayable.nil
    start.startIndex += 1
    elem
  }

  def enqueue(elem: T) = this += elem

  def +=(elem: T): this.type = {
    end += elem
    this
  }

  def foreach(f: T => Unit) {
    var node = start
    while (node != null) {
      var i = node.startIndex
      val array = node.array
      val until = node.endIndex
      while (i < until) {
        f(array(i))
        i += 1
      }
      node = node.next
    }
  }

  def newNode: Node[T] = new Node[T](this, arrayable.newRawArray(INITIAL_NODE_LENGTH))

  def clear() {
    start = newNode
    end = start
  }
}


object UnrolledBuffer {

  def INITIAL_NODE_LENGTH = 8
  def MAXIMUM_NODE_LENGTH = 128

  class Node[@specialized(Int, Long, Double) T](
    val outer: UnrolledBuffer[T], val array: Array[T]
  ) {
    private[reactors] var startIndex = 0
    private[reactors] var endIndex = 0
    private[reactors] var rawNext: Node[T] = null

    def next: Node[T] = rawNext

    def next_=(n: Node[T]) = rawNext = n

    def +=(elem: T) {
      if (endIndex < array.length) {
        array(endIndex) = elem
        endIndex += 1
      } else {
        val nlen = math.min(MAXIMUM_NODE_LENGTH, array.length * 2)
        next = new Node(outer, outer.arrayable.newRawArray(nlen))
        outer.end = next
        next += elem
      }
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy