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

scala.concurrent.stm.ccstm.TArrayImpl.scala Maven / Gradle / Ivy

The newest version!
/* scala-stm - (c) 2009-2012, Stanford University, PPL */

package scala.concurrent.stm
package ccstm

import skel.AtomicArray
import java.util.concurrent.atomic.AtomicLongArray
import scala.reflect.ClassManifest
import scala.collection._


private[ccstm] class TArrayImpl[A](private val values: AtomicArray[A])(implicit m: ClassManifest[A]) extends TArray[A] with TArray.View[A] {
  import TArray._

  def this(length0: Int)(implicit m: ClassManifest[A]) = this(AtomicArray[A](length0))

  def this(data0: TraversableOnce[A])(implicit m: ClassManifest[A]) = this(AtomicArray[A](data0))

  val length = values.length

  //////////////// TArray

  def single: View[A] = this

  def apply(index: Int)(implicit txn: InTxn) = getRef(index).get

  def update(index: Int, v: A)(implicit txn: InTxn) = getRef(index).set(v)

  /** Returns a sequence that will produce transient `Ref` instances that are
   *  backed by elements of this `TArray`.  This allows use of all of `Ref`'s
   *  functionality for reading, writing, and transforming elements.
   */
  def refs: immutable.IndexedSeq[Ref[A]] = new immutable.IndexedSeq[Ref[A]] {
    def length: Int = TArrayImpl.this.length
    def apply(index0: Int): Ref[A] = getRef(index0)
  }

  //////////////// TArray.View

  def tarray = TArrayImpl.this

  def apply(index: Int): A = getRef(index).single.get

  def update(index: Int, v: A) = getRef(index).single.set(v)

  def refViews: immutable.IndexedSeq[Ref.View[A]] = new immutable.IndexedSeq[Ref.View[A]] {
    def length = tarray.length
    def apply(index: Int) = getRef(index).single
  }

  /////////////// TxnDebuggable

  def dbgStr: String = atomic.unrecorded({ _ => mkStringPrefix("TArray", single) }, { _.toString })

  def dbgValue: Any = atomic.unrecorded({ _ => toArray }, { x => x })

  /////////////// Internal implementation

  private val metaIndexMask = {
    // We use min(length, nextPowerOfTwo(6 + length/16)) metadata elements.
    // The mask is always nextPowerOfTwo(6 + length/16) - 1, even if that is
    // too large.
    val n = 6 + length / 16
    var m = 7
    while (m < n - 1)
      m = (m << 1) + 1
    m
  }

  private val metaValues = new AtomicLongArray(math.min(metaIndexMask + 1, length))

  private def getRef(index: Int): Ref[A] = {
    if (index < 0 || index >= length)
      throw new ArrayIndexOutOfBoundsException(index)

    new Handle[A] with RefOps[A] with ViewOps[A] {
      def handle: Handle[A] = this
      def single: Ref.View[A] = this
      def ref: Ref[A] = this

      def meta = metaValues.get(metaOffset)
      def meta_=(v: Long) { metaValues.set(metaOffset, v) }
      def metaCAS(before: Long, after: Long) = metaValues.compareAndSet(metaOffset, before, after)
      def base = TArrayImpl.this
      def offset = index
      def metaOffset = index & metaIndexMask
      def data = values(index)
      def data_=(v: A) { values(index) = v }

      override def dbgStr: String = super[RefOps].dbgStr
      override def dbgValue: Any = super[RefOps].dbgValue

      override def toString = {
        "TArray@" + Integer.toHexString(System.identityHashCode(TArrayImpl.this)) + "(" + index + ")"
      }
    }
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy