Skip to content

Commit 3ef6ebf

Browse files
committed
Make List safe to share across threads without synchronization
1 parent d66bd38 commit 3ef6ebf

File tree

4 files changed

+19
-5
lines changed

4 files changed

+19
-5
lines changed

src/library/scala/collection/immutable/List.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream}
77
import scala.annotation.unchecked.uncheckedVariance
88
import scala.annotation.tailrec
99
import mutable.{Builder, ListBuffer, ReusableBuilder}
10+
import scala.runtime.ScalaRunTime
1011

1112
/** A class for immutable linked lists representing ordered collections
1213
* of elements of type `A`.
@@ -146,6 +147,7 @@ sealed abstract class List[+A]
146147
t = nx
147148
rest = rest.tail
148149
}
150+
ScalaRunTime.releaseFence()
149151
h
150152
}
151153

@@ -215,6 +217,7 @@ sealed abstract class List[+A]
215217
t = nx
216218
rest = rest.tail
217219
}
220+
ScalaRunTime.releaseFence()
218221
h
219222
}
220223
}
@@ -241,7 +244,7 @@ sealed abstract class List[+A]
241244
}
242245
rest = rest.tail
243246
} while (rest ne Nil)
244-
h
247+
{ScalaRunTime.releaseFence(); h}
245248
}
246249
}
247250

@@ -266,7 +269,7 @@ sealed abstract class List[+A]
266269
}
267270
rest = rest.tail
268271
}
269-
if (!found) Nil else h
272+
if (!found) Nil else {ScalaRunTime.releaseFence(); h}
270273
}
271274
}
272275

@@ -443,7 +446,9 @@ sealed abstract class List[+A]
443446
}
444447
}
445448
}
446-
loop(null, null, this, this)
449+
val result = loop(null, null, this, this)
450+
ScalaRunTime.releaseFence()
451+
result
447452
}
448453

449454
final override def toList: List[A] = this
@@ -470,6 +475,7 @@ sealed abstract class List[+A]
470475

471476
case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally
472477
extends List[A] {
478+
ScalaRunTime.releaseFence()
473479
override def isEmpty: Boolean = false
474480
override def headOption: Some[A] = Some(head)
475481
override def tail: List[A] = next

src/library/scala/collection/mutable/ListBuffer.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import scala.Int._
77
import scala.collection.immutable.{List, Nil, ::}
88
import scala.annotation.tailrec
99
import java.lang.{IllegalArgumentException, IndexOutOfBoundsException}
10+
import scala.runtime.ScalaRunTime
1011

1112
/** A `Buffer` implementation backed by a list. It provides constant time
1213
* prepend and append. Most other operations are linear.
@@ -63,6 +64,7 @@ class ListBuffer[A]
6364
// Avoids copying where possible.
6465
override def toList: List[A] = {
6566
aliased = nonEmpty
67+
ScalaRunTime.releaseFence()
6668
first
6769
}
6870

src/reflect/scala/reflect/internal/tpe/FindMembers.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package tpe
77

88
import util.StatisticsStatics
99
import Flags._
10+
import scala.runtime.ScalaRunTime
1011

1112
trait FindMembers {
1213
this: SymbolTable =>
@@ -282,6 +283,7 @@ trait FindMembers {
282283
} else {
283284
if (StatisticsStatics.areSomeColdStatsEnabled) statistics.incCounter(multMemberCount)
284285
lastM.next = Nil
286+
ScalaRunTime.releaseFence()
285287
initBaseClasses.head.newOverloaded(tpe, members)
286288
}
287289
}

src/reflect/scala/reflect/internal/util/Collections.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
package scala
77
package reflect.internal.util
88

9-
import scala.collection.{ mutable, immutable }
9+
import scala.collection.{immutable, mutable}
1010
import scala.annotation.tailrec
1111
import mutable.ListBuffer
12+
import scala.runtime.ScalaRunTime
1213

1314
/** Profiler driven changes.
1415
* TODO - inlining doesn't work from here because of the bug that
@@ -58,6 +59,7 @@ trait Collections {
5859
tail = next
5960
rest = rest.tail
6061
}
62+
ScalaRunTime.releaseFence()
6163
head
6264
}
6365

@@ -128,7 +130,9 @@ trait Collections {
128130
}
129131
}
130132
}
131-
loop(null, xs, xs, ys)
133+
val result = loop(null, xs, xs, ys)
134+
ScalaRunTime.releaseFence()
135+
result
132136
}
133137

134138
final def map3[A, B, C, D](xs1: List[A], xs2: List[B], xs3: List[C])(f: (A, B, C) => D): List[D] = {

0 commit comments

Comments
 (0)