summaryrefslogblamecommitdiff
path: root/src/library/scala/collection/parallel/mutable/ParCtrie.scala
blob: 37add60df9568f4733c20ae8962a39f7d562688e (plain) (tree)




























                                                                            
                                                                               
















                                                                        
                                                                                                  





























                                                               

                                                                                              


                                                                               

                                                                                    

                  





                                                                                                                                        
  





                                      







                                                                                                    

                                       









































                                                                                                                                   
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2012, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala.collection.parallel.mutable



import scala.collection.generic._
import scala.collection.parallel.Combiner
import scala.collection.parallel.IterableSplitter
import scala.collection.mutable.Ctrie
import scala.collection.mutable.CtrieIterator



/** Parallel Ctrie collection.
 *  
 *  It has its bulk operations parallelized, but uses the snapshot operation
 *  to create the splitter. This means that parallel bulk operations can be
 *  called concurrently with the modifications.
 *  
 *  @author Aleksandar Prokopec
 *  @since 2.10
 */
final class ParCtrie[K, V] private[collection] (private val ctrie: Ctrie[K, V])
extends ParMap[K, V]
   with GenericParMapTemplate[K, V, ParCtrie]
   with ParMapLike[K, V, ParCtrie[K, V], Ctrie[K, V]]
   with ParCtrieCombiner[K, V]
   with Serializable
{
  
  def this() = this(new Ctrie)
  
  override def mapCompanion: GenericParMapCompanion[ParCtrie] = ParCtrie
  
  override def empty: ParCtrie[K, V] = ParCtrie.empty
  
  protected[this] override def newCombiner = ParCtrie.newCombiner
  
  override def seq = ctrie
  
  def splitter = new ParCtrieSplitter(0, ctrie.readOnlySnapshot().asInstanceOf[Ctrie[K, V]], true)
  
  override def size = ctrie.size
  
  override def clear() = ctrie.clear()
  
  def result = this
  
  def get(key: K): Option[V] = ctrie.get(key)
  
  def put(key: K, value: V): Option[V] = ctrie.put(key, value)
  
  def update(key: K, value: V): Unit = ctrie.update(key, value)
  
  def remove(key: K): Option[V] = ctrie.remove(key)
  
  def +=(kv: (K, V)): this.type = {
    ctrie.+=(kv)
    this
  }
  
  def -=(key: K): this.type = {
    ctrie.-=(key)
    this
  }
  
  override def stringPrefix = "ParCtrie"
  
}


private[collection] class ParCtrieSplitter[K, V](lev: Int, ct: Ctrie[K, V], mustInit: Boolean)
extends CtrieIterator[K, V](lev, ct, mustInit)
   with IterableSplitter[(K, V)]
{
  // only evaluated if `remaining` is invoked (which is not used by most tasks)
  //lazy val totalsize = ct.iterator.size /* TODO improve to lazily compute sizes */
  def totalsize: Int = throw new UnsupportedOperationException
  var iterated = 0
  
  protected override def newIterator(_lev: Int, _ct: Ctrie[K, V], _mustInit: Boolean) = new ParCtrieSplitter[K, V](_lev, _ct, _mustInit)
  
  override def shouldSplitFurther[S](coll: collection.parallel.ParIterable[S], parallelismLevel: Int) = {
    val maxsplits = 3 + Integer.highestOneBit(parallelismLevel)
    level < maxsplits
  }
  
  def dup = {
    val it = newIterator(0, ct, false)
    dupTo(it)
    it.iterated = this.iterated
    it
  }
  
  override def next() = {
    iterated += 1
    super.next()
  }
  
  def split: Seq[IterableSplitter[(K, V)]] = subdivide().asInstanceOf[Seq[IterableSplitter[(K, V)]]]
  
  override def isRemainingCheap = false
  
  def remaining: Int = totalsize - iterated
}


/** Only used within the `ParCtrie`. */
private[mutable] trait ParCtrieCombiner[K, V] extends Combiner[(K, V), ParCtrie[K, V]] {
  
  def combine[N <: (K, V), NewTo >: ParCtrie[K, V]](other: Combiner[N, NewTo]): Combiner[N, NewTo] = if (this eq other) this else {
    throw new UnsupportedOperationException("This shouldn't have been called in the first place.")
    
    val thiz = this.asInstanceOf[ParCtrie[K, V]]
    val that = other.asInstanceOf[ParCtrie[K, V]]
    val result = new ParCtrie[K, V]
    
    result ++= thiz.iterator
    result ++= that.iterator
    
    result
  }
  
  override def canBeShared = true
  
}

  
object ParCtrie extends ParMapFactory[ParCtrie] {
  
  def empty[K, V]: ParCtrie[K, V] = new ParCtrie[K, V]
  
  def newCombiner[K, V]: Combiner[(K, V), ParCtrie[K, V]] = new ParCtrie[K, V]
  
  implicit def canBuildFrom[K, V]: CanCombineFrom[Coll, (K, V), ParCtrie[K, V]] = new CanCombineFromMap[K, V]
  
}