Skip to content

Commit dfa21dc

Browse files
committed
Make List safe to share across threads without synchronization
1 parent 2c6a348 commit dfa21dc

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`.
@@ -148,6 +149,7 @@ sealed abstract class List[+A]
148149
t = nx
149150
rest = rest.tail
150151
}
152+
ScalaRunTime.releaseFence()
151153
h
152154
}
153155

@@ -217,6 +219,7 @@ sealed abstract class List[+A]
217219
t = nx
218220
rest = rest.tail
219221
}
222+
ScalaRunTime.releaseFence()
220223
h
221224
}
222225
}
@@ -243,7 +246,7 @@ sealed abstract class List[+A]
243246
}
244247
rest = rest.tail
245248
} while (rest ne Nil)
246-
h
249+
{ScalaRunTime.releaseFence(); h}
247250
}
248251
}
249252

@@ -268,7 +271,7 @@ sealed abstract class List[+A]
268271
}
269272
rest = rest.tail
270273
}
271-
if (!found) Nil else h
274+
if (!found) Nil else {ScalaRunTime.releaseFence(); h}
272275
}
273276
}
274277

@@ -449,7 +452,9 @@ sealed abstract class List[+A]
449452
}
450453
}
451454
}
452-
loop(null, null, this, this)
455+
val result = loop(null, null, this, this)
456+
ScalaRunTime.releaseFence()
457+
result
453458
}
454459

455460
final override def toList: List[A] = this
@@ -477,6 +482,7 @@ sealed abstract class List[+A]
477482
@SerialVersionUID(4L)
478483
case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally
479484
extends List[A] {
485+
ScalaRunTime.releaseFence()
480486
override def isEmpty: Boolean = false
481487
override def headOption: Some[A] = Some(head)
482488
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.
@@ -66,6 +67,7 @@ class ListBuffer[A]
6667
// Avoids copying where possible.
6768
override def toList: List[A] = {
6869
aliased = nonEmpty
70+
ScalaRunTime.releaseFence()
6971
first
7072
}
7173

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)