Skip to content

Commit

Permalink
Java ConcurrentMap wrapper updateWith is compute
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed May 5, 2022
1 parent df355f9 commit a3194d4
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
Expand Up @@ -452,6 +452,10 @@ private[collection] object JavaCollectionWrappers extends Serializable {
case _ if isEmpty => None
case _ => Try(last).toOption
}

override def updateWith(key: K)(remappingFunction: Option[V] => Option[V]): Option[V] = Option {
underlying.compute(key, (_: K, v: V) => remappingFunction(Option(v)).getOrElse(null.asInstanceOf[V]))
}
}

@SerialVersionUID(3L)
Expand Down
31 changes: 29 additions & 2 deletions test/junit/scala/collection/convert/MapWrapperTest.scala
@@ -1,13 +1,14 @@
package scala.collection.convert

import java.util
import java.{util => jutil}

import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

import scala.jdk.CollectionConverters._
import scala.util.chaining._

@RunWith(classOf[JUnit4])
class MapWrapperTest {
Expand Down Expand Up @@ -63,7 +64,7 @@ class MapWrapperTest {
// regression test for https://github.com/scala/bug/issues/10663
@Test
def testHashCodeEqualsMatchesJavaMap(): Unit = {
val jmap = new util.HashMap[String, String]()
val jmap = new jutil.HashMap[String, String]()
jmap.put("scala", "rocks")
jmap.put("java interop is fun!", "ya!")
jmap.put("Ĺởồҝ ïŧ\\'ş ūŋǐčōđẹ", "whyyyy")
Expand All @@ -79,4 +80,30 @@ class MapWrapperTest {
assertTrue(jmap == mapWrapper)
assertTrue(mapWrapper == jmap)
}

// was: induce intermittent failure due to contention, where updater is called more than once
@Test def `t12586 updateWith should delegate to compute`: Unit = {
@volatile var count = 0
val jmap = new jutil.concurrent.ConcurrentHashMap[String, String]()
class Loki extends Runnable {
@volatile var done = false
def run(): Unit = {
while (!done) {
jmap.put("KEY", "VALUE")
//Thread.`yield`()
}
}
}
val loki = new Loki
val runner = new Thread(loki).tap(_.start)
val wrapped = jmap.asScala
def updater(old: Option[String]) = { count += 1 ; old.map(_ * 2) }
for (i <- 1 to 500) {
count = 0
wrapped.updateWith("KEY")(updater)
assertEquals(s"index $i", 1, count)
}
loki.done = true
runner.join()
}
}

0 comments on commit a3194d4

Please sign in to comment.