Record write-once lazy builds against repeated reads and report the cache state.

write-once lazy A coordination report can record how a write-once value is shared. A Scala `lazy val` runs its initializer the first time the value is read and caches the result, so repeated reads reuse the single build. With no reads the slot is unset, with one read it is set, and with repeated reads it is locked to the one cached build. The status line summarizes whether the slot stayed unset, set, or locked after the recorded reads, while the build counter confirms the initializer ran at most once.

Lazy Value Coordination Report

reads
LazyValueCoordinationReport.scala
Replay: real traced execution (multi-file project)
object Main {
  def main(args: Array[String]): Unit = {
    val reads = 1
    var builds = 0
    lazy val cached = {
      builds = builds + 1
      7
    }
    var served = 0

    for (i <- 0 until reads) {
      if (cached > 0) {
        served = served + 1
      }
    }

    var status = "set"
    if (builds == 0) {
      status = "unset"
    }
    if (served > 1) {
      status = "locked"
    }

    println("reads=" + reads + " served=" + served + " builds=" + builds + " " + status)
  }
}
object Main {
  def main(args: Array[String]): Unit = {
    val reads = 0
    var builds = 0
    lazy val cached = {
      builds = builds + 1
      7
    }
    var served = 0

    for (i <- 0 until reads) {
      if (cached > 0) {
        served = served + 1
      }
    }

    var status = "set"
    if (builds == 0) {
      status = "unset"
    }
    if (served > 1) {
      status = "locked"
    }

    println("reads=" + reads + " served=" + served + " builds=" + builds + " " + status)
  }
}
object Main {
  def main(args: Array[String]): Unit = {
    val reads = 2
    var builds = 0
    lazy val cached = {
      builds = builds + 1
      7
    }
    var served = 0

    for (i <- 0 until reads) {
      if (cached > 0) {
        served = served + 1
      }
    }

    var status = "set"
    if (builds == 0) {
      status = "unset"
    }
    if (served > 1) {
      status = "locked"
    }

    println("reads=" + reads + " served=" + served + " builds=" + builds + " " + status)
  }
}
  1. reads ← 1, builds ← 0, cached ← 7, served ← 0

    1object Main {2  def main(args: Array[String]): Unit = {3    val reads→ 1 = 1 //@reads=0, 24    var builds→ 0 = 05    lazy val cached→ 7 = {6      builds→ 1 = builds + 17      78    }9    var served→ 0 = 01011    for (i <- 0 until reads) {
  2. for (i <- 0 until reads)

    11for (i0 <- 0 until reads1) {12  if (cached > 0) {
  3. served ← 1

    11for (i <- 0 until reads) {12  if (cached7 > 0) {13    served→ 1 = served + 114  }15}
  4. status ← set

    17    var status→ set = "set"18    if (builds == 0) {19      status = "unset"20    }21    if (served > 1) {22      status = "locked"23    }2425    println("reads=" + reads1 + " served=" + served1 + " builds=" + builds1 + " " + statusset)26  }27}
    outputreads=1 served=1 builds=1 set
  1. reads ← 0, builds ← 0, cached ← 7, served ← 0, status ← set

    1object Main {2  def main(args: Array[String]): Unit = {3    val reads→ 0 = 04    var builds→ 0 = 05    lazy val cached→ 7 = {6      builds→ 1 = builds + 17      78    }9    var served→ 0 = 01011    for (i <- 0 until reads) {12      if (cached > 0) {13        served = served + 114      }15    }1617    var status→ set = "set"18    if (builds == 0) {19      status = "unset"20    }21    if (served > 1) {22      status = "locked"23    }2425    println("reads=" + reads0 + " served=" + served0 + " builds=" + builds1 + " " + statusset)26  }27}
    outputreads=0 served=0 builds=1 set
  1. reads ← 2, builds ← 0, cached ← 7, served ← 0

    1object Main {2  def main(args: Array[String]): Unit = {3    val reads→ 2 = 24    var builds→ 0 = 05    lazy val cached→ 7 = {6      builds→ 1 = builds + 17      78    }9    var served→ 0 = 01011    for (i <- 0 until reads) {
  2. for (i <- 0 until reads)

    pass 1 of 2
    11for (i0 <- 0 until reads2) {12  if (cached > 0) {
  3. served ← 1

    pass 1 of 2
    11for (i <- 0 until reads) {12  if (cached7 > 0) {13    served→ 1 = served + 114  }15}
  4. for (i <- 0 until reads)

    pass 2 of 2
    11for (i1 <- 0 until reads2) {12  if (cached > 0) {
  5. served ← 2

    pass 2 of 2
    11for (i <- 0 until reads) {12  if (cached7 > 0) {13    served→ 2 = served + 114  }15}
  6. status ← set

    17var status→ set = "set"18if (builds == 0) {19  status = "unset"
  7. status ← locked

    20}21if (served2 > 1) {22  status→ locked = "locked"23}
  8. println("reads=" + reads + " served=" + served + " builds=" + builds +…

    25    println("reads=" + reads2 + " served=" + served2 + " builds=" + builds1 + " " + statuslocked)26  }27}
    outputreads=2 served=2 builds=1 locked