summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/parallel/ParMapLike.scala
blob: 0a671fb0853b9ddff6f9d62afde6e9c26301afdf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2013, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala
package collection.parallel

import scala.collection.MapLike
import scala.collection.GenMapLike
import scala.collection.Map
import scala.collection.mutable.Builder
import scala.annotation.unchecked.uncheckedVariance
import scala.collection.generic.IdleSignalling
import scala.collection.generic.Signalling

/** A template trait for mutable parallel maps. This trait is to be mixed in
 *  with concrete parallel maps to override the representation type.
 *
 *  $sideeffects
 *
 *  @tparam K    the key type of the map
 *  @tparam V    the value type of the map
 *  @define Coll `ParMap`
 *  @define coll parallel map
 *
 *  @author Aleksandar Prokopec
 *  @since 2.9
 */
trait ParMapLike[K,
                 +V,
                 +Repr <: ParMapLike[K, V, Repr, Sequential] with ParMap[K, V],
                 +Sequential <: Map[K, V] with MapLike[K, V, Sequential]]
extends GenMapLike[K, V, Repr]
   with ParIterableLike[(K, V), Repr, Sequential]
{
self =>

  def default(key: K): V = throw new NoSuchElementException("key not found: " + key)

  def empty: Repr

  def apply(key: K) = get(key) match {
    case Some(v) => v
    case None => default(key)
  }

  def getOrElse[U >: V](key: K, default: => U): U = get(key) match {
    case Some(v) => v
    case None => default
  }

  def contains(key: K): Boolean = get(key).isDefined

  def isDefinedAt(key: K): Boolean = contains(key)

  private[this] def keysIterator(s: IterableSplitter[(K, V)] @uncheckedVariance): IterableSplitter[K] =
    new IterableSplitter[K] {
      i =>
      val iter = s
      def hasNext = iter.hasNext
      def next() = iter.next()._1
      def split = {
        val ss = iter.split.map(keysIterator(_))
        ss.foreach { _.signalDelegate = i.signalDelegate }
        ss
      }
      def remaining = iter.remaining
      def dup = keysIterator(iter.dup)
    }

  def keysIterator: IterableSplitter[K] = keysIterator(splitter)

  private[this] def valuesIterator(s: IterableSplitter[(K, V)] @uncheckedVariance): IterableSplitter[V] =
    new IterableSplitter[V] {
      i =>
      val iter = s
      def hasNext = iter.hasNext
      def next() = iter.next()._2
      def split = {
        val ss = iter.split.map(valuesIterator(_))
        ss.foreach { _.signalDelegate = i.signalDelegate }
        ss
      }
      def remaining = iter.remaining
      def dup = valuesIterator(iter.dup)
    }

  def valuesIterator: IterableSplitter[V] = valuesIterator(splitter)

  protected class DefaultKeySet extends ParSet[K] {
    def contains(key : K) = self.contains(key)
    def splitter = keysIterator(self.splitter)
    def + (elem: K): ParSet[K] =
      (ParSet[K]() ++ this + elem).asInstanceOf[ParSet[K]] // !!! concrete overrides abstract problem
    def - (elem: K): ParSet[K] =
      (ParSet[K]() ++ this - elem).asInstanceOf[ParSet[K]] // !!! concrete overrides abstract problem
    override def size = self.size
    override def foreach[U](f: K => U) = for ((k, v) <- self) f(k)
    override def seq = self.seq.keySet
  }

  protected class DefaultValuesIterable extends ParIterable[V] {
    def splitter = valuesIterator(self.splitter)
    override def size = self.size
    override def foreach[U](f: V => U) = for ((k, v) <- self) f(v)
    def seq = self.seq.values
  }

  def keySet: ParSet[K] = new DefaultKeySet

  def keys: ParIterable[K] = keySet

  def values: ParIterable[V] = new DefaultValuesIterable

  def filterKeys(p: K => Boolean): ParMap[K, V] = new ParMap[K, V] {
    lazy val filtered = self.filter(kv => p(kv._1))
    override def foreach[U](f: ((K, V)) => U): Unit = for (kv <- self) if (p(kv._1)) f(kv)
    def splitter = filtered.splitter
    override def contains(key: K) = self.contains(key) && p(key)
    def get(key: K) = if (!p(key)) None else self.get(key)
    def seq = self.seq.filterKeys(p)
    def size = filtered.size
    def + [U >: V](kv: (K, U)): ParMap[K, U] = ParMap[K, U]() ++ this + kv
    def - (key: K): ParMap[K, V] = ParMap[K, V]() ++ this - key
  }

  def mapValues[S](f: V => S): ParMap[K, S] = new ParMap[K, S] {
    override def foreach[U](g: ((K, S)) => U): Unit = for ((k, v) <- self) g((k, f(v)))
    def splitter = self.splitter.map(kv => (kv._1, f(kv._2)))
    override def size = self.size
    override def contains(key: K) = self.contains(key)
    def get(key: K) = self.get(key).map(f)
    def seq = self.seq.mapValues(f)
    def + [U >: S](kv: (K, U)): ParMap[K, U] = ParMap[K, U]() ++ this + kv
    def - (key: K): ParMap[K, S] = ParMap[K, S]() ++ this - key
  }

  // note - should not override toMap (could be mutable)
}