summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/mutable/AnyRefMap.scala
diff options
context:
space:
mode:
authorRex Kerr <ichoran@gmail.com>2014-01-30 11:43:26 -0800
committerRex Kerr <ichoran@gmail.com>2014-01-30 11:47:05 -0800
commitf97e2d42eb211d429b27f79fe993bf48c92e9740 (patch)
tree876b10816206ff8180e572804bb101464f560b2c /src/library/scala/collection/mutable/AnyRefMap.scala
parent0e578e693196f93b1ba4f972a2c96d468bef464a (diff)
downloadscala-f97e2d42eb211d429b27f79fe993bf48c92e9740.tar.gz
scala-f97e2d42eb211d429b27f79fe993bf48c92e9740.tar.bz2
scala-f97e2d42eb211d429b27f79fe993bf48c92e9740.zip
SI-8213 AnyRefMap.getOrElseUpdate is faulty
Altered getOrElseUpdate to be robust to the map changing out from under it as a result of calling the default value method. Side-effects FTW! Made a comparable change in LongMap also, as it was also affected. And added a test to SetMapConsistencyTest.
Diffstat (limited to 'src/library/scala/collection/mutable/AnyRefMap.scala')
-rw-r--r--src/library/scala/collection/mutable/AnyRefMap.scala15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala
index df74bb5187..29c92a111c 100644
--- a/src/library/scala/collection/mutable/AnyRefMap.scala
+++ b/src/library/scala/collection/mutable/AnyRefMap.scala
@@ -129,9 +129,20 @@ extends AbstractMap[K, V]
override def getOrElseUpdate(key: K, defaultValue: => V): V = {
val h = hashOf(key)
- val i = seekEntryOrOpen(h, key)
+ var i = seekEntryOrOpen(h, key)
if (i < 0) {
- val value = defaultValue
+ // It is possible that the default value computation was side-effecting
+ // Our hash table may have resized or even contain what we want now
+ // (but if it does, we'll replace it)
+ val value = {
+ val oh = _hashes
+ val ans = defaultValue
+ if (oh ne _hashes) {
+ i = seekEntryOrOpen(h, key)
+ if (i >= 0) _size -= 1
+ }
+ ans
+ }
_size += 1
val j = i & IndexMask
_hashes(j) = h