-
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.
This strategy ensures the "serializability" condition of parallel programs--not to be confused with the data being `java.io.Serializable`. Indeed, if thread A is evaluating the lazy val while thread B attempts to serialize its owner object, there is also an alternative schedule where thread B serializes the owner object *before* A starts evaluating the lazy val. Therefore, forcing B to see the non-evaluating state is correct.
- Loading branch information
Showing
3 changed files
with
89 additions
and
2 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
succeeded: BOMB: test |
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,70 @@ | ||
// scalajs: --skip | ||
|
||
import java.io.* | ||
|
||
class Message(content: String) extends Serializable: | ||
//@transient | ||
lazy val bomb: String = | ||
Thread.sleep(200) | ||
"BOMB: " + content | ||
end Message | ||
|
||
object Test: | ||
def serialize(obj: Message): Array[Byte] = | ||
val byteStream = ByteArrayOutputStream() | ||
val objectStream = ObjectOutputStream(byteStream) | ||
try | ||
objectStream.writeObject(obj) | ||
byteStream.toByteArray | ||
finally | ||
objectStream.close() | ||
byteStream.close() | ||
end serialize | ||
|
||
def deserialize(bytes: Array[Byte]): Message = | ||
val byteStream = ByteArrayInputStream(bytes) | ||
val objectStream = ObjectInputStream(byteStream) | ||
try | ||
objectStream.readObject().asInstanceOf[Message] | ||
finally | ||
objectStream.close() | ||
byteStream.close() | ||
end deserialize | ||
|
||
def main(args: Array[String]): Unit = | ||
val bytes = | ||
val msg = Message("test") | ||
|
||
val touch = Thread(() => { | ||
msg.bomb // start evaluation before serialization | ||
() | ||
}) | ||
touch.start() | ||
|
||
Thread.sleep(50) // give some time for the fork to start lazy val rhs eval | ||
|
||
serialize(msg) // serialize in the meantime so that we capture Waiting state | ||
end bytes | ||
|
||
val deserializedMsg = deserialize(bytes) | ||
|
||
@volatile var msg = "" | ||
@volatile var started = false | ||
val read = Thread(() => { | ||
started = true | ||
msg = deserializedMsg.bomb | ||
() | ||
}) | ||
read.start() | ||
|
||
Thread.sleep(1000) | ||
if !started then | ||
throw Exception("ouch, the thread has not started yet after 1s") | ||
|
||
if !msg.isEmpty() then | ||
println(s"succeeded: $msg") | ||
else | ||
read.interrupt() | ||
throw new AssertionError("failed to read bomb in 1s!") | ||
end main | ||
end Test |