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

scala.concurrent.stm.TSet.scala Maven / Gradle / Ivy

/* scala-stm - (c) 2009-2010, Stanford University, PPL */

package scala.concurrent.stm

import scala.collection.{immutable, mutable, generic}


object TSet {

  object View extends generic.MutableSetFactory[TSet.View] {

    implicit def canBuildFrom[A]: generic.CanBuildFrom[Coll, A, TSet.View[A]] = setCanBuildFrom[A]

    override def empty[A] = TSet.empty[A].single

    override def newBuilder[A] = new mutable.Builder[A, View[A]] {
      private val underlying = TSet.newBuilder[A]

      def clear() { underlying.clear() }
      def += (x: A): this.type = { underlying += x ; this }
      def result() = underlying.result().single
    }

    override def apply[A](xs: A*): TSet.View[A] = (TSet.newBuilder[A] ++= xs).result().single
  }

  /** A `Set` that provides atomic execution of all of its methods. */
  trait View[A] extends mutable.Set[A] with mutable.SetLike[A, View[A]] {

    /** Returns the `TSet` perspective on this transactional set, which
     *  provides set functionality only inside atomic blocks.
     */
    def tset: TSet[A]

    def clone: TSet.View[A]

    /** Takes an atomic snapshot of this transactional set. */
    def snapshot: immutable.Set[A]

    override def empty: View[A] = TSet.empty[A].single
    override def companion: generic.GenericCompanion[View] = View    
    override protected[this] def newBuilder: mutable.Builder[A, View[A]] = View.newBuilder[A]
  }
  

  /** Constructs and returns a new empty `TSet`. */
  def empty[A]: TSet[A] = impl.STMImpl.instance.newTSet[A]

  /** Returns a builder of `TSet`. */
  def newBuilder[A]: mutable.Builder[A, TSet[A]] = impl.STMImpl.instance.newTSetBuilder[A]

  /** Constructs and returns a new `TSet` that will contain the elements from
   *  `xs`.
   */
  def apply[A](xs: A*): TSet[A] = (newBuilder[A] ++= xs).result()


  /** Allows a `TSet` in a transactional context to be used as a `Set`. */
  implicit def asSet[A](s: TSet[A])(implicit txn: InTxn): View[A] = s.single
}


/** A transactional set implementation that requires that all of its set-like
 *  operations be called from inside an atomic block.  Rather than extending
 *  `Set`, an implicit conversion is provided from `TSet` to `Set` if the
 *  current scope is part of an atomic block (see `TSet.asSet`).
 *
 *  The elements (with type `A`) must be immutable, or at least not modified
 *  while they are in the set.  The `TSet` implementation assumes that it can
 *  safely perform equality and hash checks outside a transaction without
 *  affecting atomicity. 
 *
 *  @author Nathan Bronson
 */
trait TSet[A] {

  /** Returns an instance that provides transactional set functionality without
   *  requiring that operations be performed inside the static scope of an
   *  atomic block.
   */
  def single: TSet.View[A]

  def clone(implicit txn: InTxn): TSet[A] = single.clone.tset

  // The following methods work fine via the asSet mechanism, but are heavily
  // used.  We add transactional versions of them to allow overrides.

  def isEmpty(implicit txn: InTxn): Boolean
  def size(implicit txn: InTxn): Int
  def foreach[U](f: A => U)(implicit txn: InTxn)
  def contains(elem: A)(implicit txn: InTxn): Boolean
  def apply(elem: A)(implicit txn: InTxn): Boolean = contains(elem)
  def add(elem: A)(implicit txn: InTxn): Boolean
  def update(elem: A, included: Boolean)(implicit txn: InTxn) { if (included) add(elem) else remove(elem) }
  def remove(elem: A)(implicit txn: InTxn): Boolean

  // The following methods return the wrong receiver when invoked via the asSet
  // conversion.  They are exactly the methods of mutable.Set whose return type
  // is this.type.
  
  def += (x: A)(implicit txn: InTxn): this.type = { add(x) ; this }
  def += (x1: A, x2: A, xs: A*)(implicit txn: InTxn): this.type = { this += x1 += x2 ++= xs }
  def ++= (xs: TraversableOnce[A])(implicit txn: InTxn): this.type = { for (x <- xs) this += x ; this }
  def -= (x: A)(implicit txn: InTxn): this.type = { remove(x) ; this }
  def -= (x1: A, x2: A, xs: A*)(implicit txn: InTxn): this.type = { this -= x1 -= x2 --= xs }
  def --= (xs: TraversableOnce[A])(implicit txn: InTxn): this.type = { for (x <- xs) this -= x ; this }

  def retain(p: A => Boolean)(implicit txn: InTxn): this.type
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy