summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2010-09-02 13:15:21 +0000
committerIulian Dragos <jaguarul@gmail.com>2010-09-02 13:15:21 +0000
commit93fe8b8d9252297652d85d7f51965daa657676aa (patch)
tree5884cbbfd1dfd5d2ad75471483d012b0eb794079
parent21af53483f83d91e69fec7097ecbe9e1524ca30c (diff)
downloadscala-93fe8b8d9252297652d85d7f51965daa657676aa.tar.gz
scala-93fe8b8d9252297652d85d7f51965daa657676aa.tar.bz2
scala-93fe8b8d9252297652d85d7f51965daa657676aa.zip
Merged revisions 22897 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r22897 | dragos | 2010-09-01 18:01:59 +0200 (Wed, 01 Sep 2010) | 1 line Closes #1220. Stream.tail is now thread safe. Review by odersky. ........
-rw-r--r--src/library/scala/collection/immutable/Stream.scala10
-rw-r--r--test/files/run/concurrent-stream.check3
-rw-r--r--test/files/run/concurrent-stream.scala36
3 files changed, 46 insertions, 3 deletions
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 7660a1e2c8..40f71aa845 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -557,10 +557,14 @@ object Stream extends SeqFactory[Stream] {
final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] {
override def isEmpty = false
override def head = hd
- private[this] var tlVal: Stream[A] = _
- def tailDefined = tlVal ne null
+ @volatile private[this] var tlVal: Stream[A] = _
+ def tailDefined: Boolean = tlVal ne null
override def tail: Stream[A] = {
- if (!tailDefined) { tlVal = tl }
+ if (!tailDefined)
+ synchronized {
+ if (!tailDefined) tlVal = tl
+ }
+
tlVal
}
}
diff --git a/test/files/run/concurrent-stream.check b/test/files/run/concurrent-stream.check
new file mode 100644
index 0000000000..d4adf84490
--- /dev/null
+++ b/test/files/run/concurrent-stream.check
@@ -0,0 +1,3 @@
+Testing standard cons.
+Evaluation 0: List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+Evaluation 1: List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
diff --git a/test/files/run/concurrent-stream.scala b/test/files/run/concurrent-stream.scala
new file mode 100644
index 0000000000..42c695964e
--- /dev/null
+++ b/test/files/run/concurrent-stream.scala
@@ -0,0 +1,36 @@
+// test concurrent calls to Stream.tail
+object Test {
+
+def slowRange(from: Int, until: Int, cons: (Int, => Stream[Int]) => Stream[Int]): Stream[Int] = {
+ var current = from
+ def next: Stream[Int] = {
+ Thread.sleep(100)
+ if (current >= until) Stream.empty
+ else {
+ val stream = cons(current, next)
+ current += 1
+ stream
+ }
+ }
+ next
+}
+
+def testCons(cons: (Int, => Stream[Int]) => Stream[Int]): Unit = {
+ import scala.actors.Actor._
+
+ val stream = slowRange(0, 10, cons)
+ val main = self
+ actor { main ! stream.toList }
+ actor { main ! stream.toList }
+ val eval0 = receive { case list: List[Int] => list }
+ val eval1 = receive { case list: List[Int] => list }
+ println("Evaluation 0: " + eval0)
+ println("Evaluation 1: " + eval1)
+}
+
+ def main(args: Array[String]) {
+ println("Testing standard cons.")
+ testCons(Stream.cons.apply(_, _))
+ }
+}
+