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

scala.concurrent.stm.impl.STMImpl.scala Maven / Gradle / Ivy

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

package scala.concurrent.stm
package impl

import java.util.concurrent.TimeUnit

private[impl] object STMImplHolder {
  var instance: STMImpl = STMImpl.createInstance()
}

/** `STMImpl` gathers all of the functionality required to plug an STM
 *  implementation into `scala.concurrent.stm`.  Only one implementation can
 *  be selected, because `Ref`s and atomic blocks from different STM
 *  implementations are not compatible.  `STMImpl.instance` returns the
 *  `STMImpl` instance that has been selected for this program execution.
 *
 *  There are two ways to explicitly select the `STMImpl` instance:
 *
 *  1. set the JVM system property "scala.stm.impl" to the name of a class
 *     that implements `STMImpl`; or
 *
 *  2. arrange for `STMImpl.select` or `STMImpl.trySelect` to be called
 *     before any `Ref`s are constructed and before any atomic blocks are
 *     executed.
 *
 *  Setting the JVM system property "scala.stm.impl" is equivalent to making a
 *  call to `STMImpl.select(System.getProperty("scala.stm.impl"))` before any
 *  other `STMImpl` selections.
 *
 *  If there is no explicitly selected `STMImpl` instance and the classpath
 *  contains a class `scala.concurrent.stm.impl.DefaultFactory` that extends
 *  `scala.concurrent.stm.impl.STMImpl.Factory`, then an instance of that
 *  class will be instantiated and used to generate the `STMImpl` instance.
 *  ScalaSTM implementations are encouraged to implement `DefaultFactory` so
 *  that if a user includes the implementation's JAR file, it will be
 *  automatically selected.
 *
 *  If no explicit selection has been made and there is no definition of
 *  `scala.concurrent.stm.impl.DefaultFactory` present in the classpath, then
 *  ScalaSTM will fall back to the reference implementation
 *  "scala.concurrent.stm.ccstm.CCSTM".
 *
 *  @author Nathan Bronson
 */
object STMImpl {
  trait Factory {
    def createInstance(): STMImpl
  }

  /** Returns the instance of `STMImpl` that should be used to implement all
   *  ScalaSTM functionality.  Calling this method forces the implementation
   *  to be chosen if it has not already been selected.
   */
  def instance: STMImpl = STMImplHolder.instance

  // We duplicate the implementation of select() to avoid the need to
  // instantiate an STM that we won't end up using

  /** If no `STMImpl` instance has yet been selected, installs an instance of
   *  `Class.forName(implClassName)` as the system-wide STM implementation.
   *  Returns true if `implClassName` was newly or previously selected, or
   *  returns false if another STM implementation was chosen.
   */
  def trySelect(implClassName: String): Boolean = {
    explicitChoice = implClassName
    instance.getClass.getName == implClassName
  }

  /** Installs `Class.forName(implClassName)` as the system-wide STM
   *  implementation if no `STMImpl` has yet been chosen, or verifies that
   *  `implClassName` was previously selected, throwing 
   *  `IllegalStateException` if a different STM implementation has already
   *  been selected
   */
  def select(implClassName: String) {
    if (!trySelect(implClassName)) {
      throw new IllegalStateException(
          "unable to select STMImpl class " + implClassName + ", " + instance + " already installed");
    }
  }

  /** Installs `impl` as the system-wide STM implementation if no `STMImpl`
   *  has yet been chosen, or verifies that `impl` is equal to the previously
   *  selected instance, throwing `IllegalStateException` if an STM
   *  implementation has already been selected and `impl != instance`
   */
  def select(impl: STMImpl) {
    explicitChoice = impl
    if (impl != instance) {
      throw new IllegalStateException(
          "unable to select STMImpl " + impl + ", " + instance + " already installed");
    }
  }


  /** May be a String class name, an STMImpl, or null */
  @volatile private var explicitChoice: AnyRef = null

  private[impl] def createInstance(): STMImpl = {
    var choice: AnyRef = System.getProperty("scala.stm.impl")

    if (choice == null)
      choice = explicitChoice

    if (choice == null) {
      choice = (try {
        val fc = Class.forName("scala.concurrent.stm.impl.DefaultFactory")
        fc.newInstance().asInstanceOf[STMImpl.Factory].createInstance()
      } catch {
        case _: ClassNotFoundException => "scala.concurrent.stm.ccstm.CCSTM"
      })
    }

    choice match {
      case s: String => Class.forName(s).newInstance().asInstanceOf[STMImpl]
      case i: STMImpl => i
    }
  }
}

/** `STMImpl` gathers all of the functionality required to plug an STM
 *  implementation into `scala.concurrent.stm`.  See the `STMImpl` companion
 *  object for information on controlling which `STMImpl` is selected at run
 *  time.
 *
 *  @author Nathan Bronson
 */
trait STMImpl extends RefFactory with TxnContext with TxnExecutor {

  /** Returns a new commit barrier suitable for coordinating commits by this
   *  STM implementation.
   */
  def newCommitBarrier(timeout: Long, unit: TimeUnit): CommitBarrier
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy