8000 Offer stronger guarantees under the Java Memory Model for List & Vector (using releaseFence) by retronym · Pull Request #6425 · scala/scala · GitHub
[go: up one dir, main page]

Skip to content

Offer stronger guarantees under the Java Memory Model for List & Vector (using releaseFence) #6425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 18, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
More fences and commentary
  • Loading branch information
retronym committed Aug 16, 2018
commit b6d74ff9a52f15eef0a7455bf1fcfba7be824178
2 changes: 2 additions & 0 deletions src/library/scala/collection/immutable/List.scala
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,8 @@ sealed abstract class List[+A]

}

// Internal code that mutates `next` _must_ call `ScalaRunTime.releaseFence()` if either immediately, or
// before a newly-allocated, thread-local :: instance is aliased (e.g. in ListBuffer.toList)
final case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally
extends List[A] {
ScalaRunTime.releaseFence()
Expand Down
5 changes: 5 additions & 0 deletions src/library/scala/collection/immutable/Vector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ final class Vector[+A] private[immutable] (private[collection] val startIndex: I

override def iterableFactory: SeqFactory[Vector] = Vector

// Code paths that mutates `dirty` _must_ call `ScalaRunTime.releaseFence()` before returning from
// the public method.
private[immutable] var dirty = false
// While most JDKs would implicit add this fence because of >= 1 final field, the spec only mandates
// it if all fields are final, so let's add this in explicitly.
ScalaRunTime.releaseFence()

def length: Int = endIndex - startIndex

Expand Down
3 changes: 3 additions & 0 deletions src/library/scala/collection/mutable/ListBuffer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class ListBuffer[A]
// Avoids copying where possible.
override def toList: List[A] = {
aliased = nonEmpty
// We've accumulated a number of mutations to `List.tail` by this stage.
// Make sure they are visible to threads that the client of this ListBuffer might be about
// to share this List with.
ScalaRunTime.releaseFence()
first
Copy link
Member Author
@retronym retronym Aug 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Echoing @adriaanm's comments from #7028 that belong over in this PR.

Why no fence for the other methods that mutate? I see they're private, but they are called from public methods, I assume?

My rationale is that this is the where the reference to the List is given out. Only after this point could client code share it with another thread. My assumption is that users are only using the ListBuilder itself on a single thread, and its only the resulting List that needs to be safely publishible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to add the fence after each mutation of tail, at least initially, to make things easier to reason about.

}
Expand Down
0