summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMaxim Valyanskiy <max.valjanski@gmail.com>2014-10-17 23:19:54 +0400
committerMaxim Valyanskiy <max.valjanski@gmail.com>2014-11-27 09:36:26 +0300
commit0bb8a139e9c46e3e1b4bd7af5dd11cb689ebbe8e (patch)
tree4141ea2586e252202447603071bb5fa348ce7b76 /test
parent3ac6eabae685f08fb349ddab16cbaa1c6e97984b (diff)
downloadscala-0bb8a139e9c46e3e1b4bd7af5dd11cb689ebbe8e.tar.gz
scala-0bb8a139e9c46e3e1b4bd7af5dd11cb689ebbe8e.tar.bz2
scala-0bb8a139e9c46e3e1b4bd7af5dd11cb689ebbe8e.zip
SI-8924 don't hold reference to list in iterator
Current implementation of LinearSeqLike.iterator holds reference to complete sequence. This prevent garbage collecting of List elements while we keep reference to iterator somewhere. This commit removes reference from Iterator implementation. This allow garbage collection of List while we iterating over its elements (when there is no other references to List in our program).
Diffstat (limited to 'test')
-rw-r--r--test/junit/scala/collection/immutable/ListTest.scala49
1 files changed, 49 insertions, 0 deletions
diff --git a/test/junit/scala/collection/immutable/ListTest.scala b/test/junit/scala/collection/immutable/ListTest.scala
new file mode 100644
index 0000000000..1006801029
--- /dev/null
+++ b/test/junit/scala/collection/immutable/ListTest.scala
@@ -0,0 +1,49 @@
+package scala.collection.immutable
+
+import org.junit.{Assert, Test}
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import scala.ref.WeakReference
+
+@RunWith(classOf[JUnit4])
+class ListTest {
+ /**
+ * Test that empty iterator does not hold reference
+ * to complete List
+ */
+ @Test
+ def testIteratorGC(): Unit = {
+ var num = 0
+ var emptyIterators = Seq.empty[(Iterator[Int], WeakReference[List[Int]])]
+
+ do {
+ val list = List.fill(10000)(num)
+ val ref = WeakReference(list)
+
+ val i = list.iterator
+
+ while (i.hasNext) i.next()
+
+ emptyIterators = (i, ref) +: emptyIterators
+
+ num+=1
+ } while (emptyIterators.forall(_._2.get.isDefined) && num<1000)
+
+ // check something is result to protect from JIT optimizations
+ for ((i, _) <- emptyIterators) {
+ Assert.assertTrue(i.isEmpty)
+ }
+
+ // await gc up to ~5 seconds
+ var forceLoops = 50
+ while (emptyIterators.forall(_._2.get.isDefined) && forceLoops>0) {
+ System.gc()
+ Thread.sleep(100)
+ forceLoops -= 1
+ }
+
+ // real assertion
+ Assert.assertTrue(emptyIterators.exists(_._2.get.isEmpty))
+ }
+}