-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix race condition in new LazyVals (#16975)
Resolve #16806 In the repro, `Evaluating` was generated as a subtype of `Serializable`, and the type of lazy value was erased to `Serializable` - these together broke the optimized condition checking if the value is initialized. For lazy val of type `A` we were checking if `LazyValControlState <: A`, and if that was not the case, we assumed it would be safe to just generate the condition `_value.isInstanceOf[A]`. If that condition was true in runtime, we assumed that the value was already calculated and returned it. If it was `Evaluating` and `A =:= Serializable`, then we assumed so falsely. The easiest fix is to just make the `LazyValControlState <: Serializable`, I will check if it doesn't affect performance.
- Loading branch information
Showing
4 changed files
with
51 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Success | ||
Success |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
//scalajs: --skip | ||
import java.util.concurrent.Semaphore | ||
|
||
object Repro { | ||
|
||
case object DFBit | ||
final class DFError extends Exception("") | ||
final class DFType[+T](val value: T | DFError) extends AnyVal | ||
|
||
def asIR(dfType: DFType[DFBit.type]): DFBit.type = dfType.value match | ||
case dfTypeIR: DFBit.type => dfTypeIR | ||
case err: DFError => throw new DFError | ||
|
||
object Holder { | ||
val s = new Semaphore(1, false) | ||
final lazy val Bit = { | ||
s.release() | ||
new DFType[DFBit.type](DFBit) | ||
} | ||
} | ||
|
||
@main | ||
def Test = | ||
val a = new Thread() { | ||
override def run(): Unit = | ||
Holder.s.acquire() | ||
val x = Holder.Bit.value | ||
assert(x.isInstanceOf[DFBit.type]) | ||
println("Success") | ||
} | ||
val b = new Thread() { | ||
override def run(): Unit = | ||
Holder.s.acquire() | ||
val x = Holder.Bit.value | ||
assert(x.isInstanceOf[DFBit.type]) | ||
println("Success") | ||
} | ||
a.start() | ||
b.start() | ||
a.join(300) | ||
b.join(300) | ||
} |