Lambda in REPL (using object-wrappers) + concurrency = deadlock · Issue #9076 · scala/bug (original) (raw)
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[i [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 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mi>i</mi><mi>n</mi><mi>e</mi><mn>6.</mn></mrow><annotation encoding="application/x-tex">line6.</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">in</span><span class="mord mathnormal">e</span><span class="mord">6.</span></span></span></span>read$$iw$$iw$$anonfun$1.apply(<console>:11)
at <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mi>i</mi><mi>n</mi><mi>e</mi><mn>6.</mn></mrow><annotation encoding="application/x-tex">line6.</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">in</span><span class="mord mathnormal">e</span><span class="mord">6.</span></span></span></span>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.)