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

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

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

package scala.concurrent.stm
package ccstm

import scala.util.control.ControlThrowable

private[ccstm] object CCSTMExecutor {
  val DefaultControlFlowTest = { x: Throwable => x.isInstanceOf[ControlThrowable] }

  val DefaultPostDecisionFailureHandler = { (status: Txn.Status, x: Throwable) =>
    new Exception("status=" + status, x).printStackTrace()
  }
}

private[ccstm] case class CCSTMExecutor private (
       retryTimeoutNanos: Option[Long],
       controlFlowTest: Throwable => Boolean,
       postDecisionFailureHandler: (Txn.Status, Throwable) => Unit
    ) extends TxnExecutor {

  def this() = this(None, CCSTMExecutor.DefaultControlFlowTest, CCSTMExecutor.DefaultPostDecisionFailureHandler)

  def apply[Z](block: InTxn => Z)(implicit mt: MaybeTxn): Z = InTxnImpl().atomic(this, block)

  def oneOf[Z](blocks: (InTxn => Z)*)(implicit mt: MaybeTxn): Z = InTxnImpl().atomicOneOf(this, blocks)

  def unrecorded[Z](block: InTxn => Z, outerFailure: Txn.RollbackCause => Z)(implicit mt: MaybeTxn) = {
    InTxnImpl().unrecorded(this, block, outerFailure)
  }

  def pushAlternative[Z](mt: MaybeTxn, block: (InTxn) => Z): Boolean = InTxnImpl().pushAlternative(block)

  def compareAndSet[A, B](a: Ref[A], a0: A, a1: A, b: Ref[B], b0: B, b1: B): Boolean = {
    val ah = a.asInstanceOf[Handle.Provider[A]].handle
    val bh = b.asInstanceOf[Handle.Provider[B]].handle
    InTxnImpl.dynCurrentOrNull match {
      case null => NonTxn.transform2[A, B, Boolean](ah, bh, { (av, bv) => if (a0 == av && b0 == bv) (a1, b1, true) else (av, bv, false) })
      case txn => a0 == txn.get(ah) && b0 == txn.get(bh) && { txn.set(ah, a1) ; txn.set(bh, b1) ; true }
    }
  }

  def compareAndSetIdentity[A <: AnyRef, B <: AnyRef](a: Ref[A], a0: A, a1: A, b: Ref[B], b0: B, b1: B): Boolean = {
    val aRead = a0 eq a1
    val bRead = b0 eq b1
    if (aRead && bRead)
      cci(a, a0, b, b0)
    else if (aRead)
      ccasi(a, a0, b, b0, b1)
    else if (bRead)
      ccasi(b, b0, a, a0, a1)
    else
      dcasi(a, a0, a1, b, b0, b1)
  }

  private def cci[A <: AnyRef, B <: AnyRef](a: Ref[A], a0: A, b: Ref[B], b0: B): Boolean = {
    val ah = a.asInstanceOf[Handle.Provider[A]].handle
    val bh = b.asInstanceOf[Handle.Provider[B]].handle
    InTxnImpl.dynCurrentOrNull match {
      case null => NonTxn.cci(ah, a0, bh, b0)
      case txn => (a0 eq txn.get(ah)) && (b0 eq txn.get(bh))
    }
  }

  private def ccasi[A <: AnyRef, B <: AnyRef](a: Ref[A], a0: A, b: Ref[B], b0: B, b1: B): Boolean = {
    val ah = a.asInstanceOf[Handle.Provider[A]].handle
    val bh = b.asInstanceOf[Handle.Provider[B]].handle
    InTxnImpl.dynCurrentOrNull match {
      case null => NonTxn.ccasi(ah, a0, bh, b0, b1)
      case txn => (a0 eq txn.get(ah)) && (b0 eq txn.get(bh)) && { txn.set(bh, b1) ; true }
    }
  }

  private def dcasi[A <: AnyRef, B <: AnyRef](a: Ref[A], a0: A, a1: A, b: Ref[B], b0: B, b1: B): Boolean = {
    val ah = a.asInstanceOf[Handle.Provider[A]].handle
    val bh = b.asInstanceOf[Handle.Provider[B]].handle
    InTxnImpl.dynCurrentOrNull match {
      case null => NonTxn.transform2[A, B, Boolean](ah, bh, { (av, bv) => if ((a0 eq av) && (b0 eq bv)) (a1, b1, true) else (av, bv, false) })
      case txn => (a0 eq txn.get(ah)) && (b0 eq txn.get(bh)) && { txn.set(ah, a1) ; txn.set(bh, b1) ; true }
    }
  }

  def withRetryTimeoutNanos(timeout: Option[Long]): TxnExecutor = copy(retryTimeoutNanos = timeout)

  def isControlFlow(x: Throwable): Boolean = controlFlowTest(x)
  
  def withControlFlowRecognizer(pf: PartialFunction[Throwable, Boolean]): TxnExecutor = {
    copy(controlFlowTest = { x: Throwable => if (pf.isDefinedAt(x)) pf(x) else controlFlowTest(x) })
  }

  def withPostDecisionFailureHandler(handler: (Txn.Status, Throwable) => Unit): TxnExecutor = {
    copy(postDecisionFailureHandler = handler)
  }

  override def toString: String = {
    ("CCSTMExecutor@" + hashCode.toHexString +
      "(retryTimeoutNanos=" + retryTimeoutNanos +
      ", controlFlowTest=" +
      (if (controlFlowTest eq CCSTMExecutor.DefaultControlFlowTest) "default" else controlFlowTest) +
      ", postDecisionFailureHandler=" +
      (if (postDecisionFailureHandler eq CCSTMExecutor.DefaultPostDecisionFailureHandler) "default" else postDecisionFailureHandler) +
      ")")
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy