Skip to content

Lambda in REPL (using object-wrappers) + concurrency = deadlock #9076

Closed
scala/scala
#8748
@scabug

Description

@scabug

The following code is a test of generating and using java.util.Spliterator to create a java.util.stream.Stream:

package xp

import java.util.Spliterator
import java.util.function.Consumer

class Aspi(a: Array[String], private val i0: Int, private var i1: Int) extends Spliterator[String] {
  private var i = i0
  def characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE
  def estimateSize = i1-i
  override def getExactSizeIfKnown = i1-i
  def tryAdvance(f: Consumer[_ >: String]): Boolean = {
    println(s"Trying at $i [$i0, $i1)")
    if (i >= i1) false
    else { f.accept(a(i)); i += 1; true }
  }
  def trySplit(): Aspi = {
    if (i1-i < 4) {
      println(s"Could not split [$i $i1)")
      null
    }
    else {
      println(s"Splitting from [$i $i1)")
      val child = new Aspi(a, (i+i1+1)/2, i1)
      i1 = child.i0
      child
    }
  }
}

object Test { def main(args: Array[String]) {
  def nu = new xp.Aspi(Array("one", "two", "three", "four", "five"), 0, 5)
  val st = java.util.stream.StreamSupport.stream(nu, true)
  val c = new java.util.Comparator[String]{ def compare(s: String, t: String) = s compareTo t }
  println(st.map[String]((s: String) => s + s).max(c))

This compiles and runs successfully. However, when the contents of main are entered in the REPL, the last line hangs. Stack trace:

"ForkJoinPool.commonPool-worker-1" #14 daemon prio=5 os_prio=0 tid=0x00007f966855f800 nid=0x721f in Object.wait() [0x00007f964a18b000]
   java.lang.Thread.State: RUNNABLE
	at $line6.$read$$iw$$iw$$anonfun$1.apply(<console>:11)
	at $line6.$read$$iw$$iw$$anonfun$1.apply(<console>:11)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at xp.Aspi.tryAdvance(Test.scala:14)
	at java.util.Spliterator.forEachRemaining(Spliterator.java:326)
        ...

Explicitly creating the SAM like so:

println(st.map[String](new java.util.function.Function[String, String] {
  def apply(s: String) = s + s
}).max(c))

solves the issue. (Note: I have not tried this on 2.11.5; I assumed 2.12.x was up to date in anything relevant.)

Metadata

Metadata

Assignees

Labels

Lightbend supportfixed in Scala 3This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/)has PRrepl

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions