Record arrivals counted down against a latch and report whether the barrier released.

countdown latch A coordination report can record progress toward a barrier. An `AtomicInteger` started at a fixed count models a countdown latch, and each `decrementAndGet` records one arrival while `get` reports how many arrivals are still missing. With no arrivals the latch is still waiting, with some arrivals it is partial, and once the count reaches zero the barrier is released. The status line summarizes whether the latch stayed waiting, partial, or released after the recorded arrivals.

Countdown Latch Coordination Report

arrivals
CountdownLatchCoordinationReport.scala
Replay: real traced execution (multi-file project)
import java.util.concurrent.atomic.AtomicInteger

object Main {
  def main(args: Array[String]): Unit = {
    val arrivals = 2
    val needed = 3
    val latch = new AtomicInteger(needed)
    var counted = 0

    for (i <- 0 until arrivals) {
      latch.decrementAndGet()
      counted = counted + 1
    }

    val remaining = latch.get()

    var status = "partial"
    if (counted == 0) {
      status = "waiting"
    }
    if (remaining == 0) {
      status = "released"
    }

    println("arrivals=" + arrivals + " counted=" + counted + " remaining=" + remaining + " " + status)
  }
}
import java.util.concurrent.atomic.AtomicInteger

object Main {
  def main(args: Array[String]): Unit = {
    val arrivals = 0
    val needed = 3
    val latch = new AtomicInteger(needed)
    var counted = 0

    for (i <- 0 until arrivals) {
      latch.decrementAndGet()
      counted = counted + 1
    }

    val remaining = latch.get()

    var status = "partial"
    if (counted == 0) {
      status = "waiting"
    }
    if (remaining == 0) {
      status = "released"
    }

    println("arrivals=" + arrivals + " counted=" + counted + " remaining=" + remaining + " " + status)
  }
}
import java.util.concurrent.atomic.AtomicInteger

object Main {
  def main(args: Array[String]): Unit = {
    val arrivals = 3
    val needed = 3
    val latch = new AtomicInteger(needed)
    var counted = 0

    for (i <- 0 until arrivals) {
      latch.decrementAndGet()
      counted = counted + 1
    }

    val remaining = latch.get()

    var status = "partial"
    if (counted == 0) {
      status = "waiting"
    }
    if (remaining == 0) {
      status = "released"
    }

    println("arrivals=" + arrivals + " counted=" + counted + " remaining=" + remaining + " " + status)
  }
}
  1. arrivals ← 2, needed ← 3, latch ← 3, counted ← 0

    3object Main {4  def main(args: Array[String]): Unit = {5    val arrivals→ 2 = 2 //@arrivals=0, 36    val needed→ 3 = 37    val latch→ 3 = new AtomicInteger(needed3)8    var counted→ 0 = 0910    for (i <- 0 until arrivals) {
  2. latch ← 2, counted ← 1

    pass 1 of 2
    10for (i0 <- 0 until arrivals2) {11  latch→ 2.decrementAndGet()12  counted→ 1 = counted + 113}
  3. latch ← 1, counted ← 2

    pass 2 of 2
    10for (i1 <- 0 until arrivals2) {11  latch→ 1.decrementAndGet()12  counted→ 2 = counted + 113}
  4. remaining ← 1, status ← partial

    15    val remaining→ 1 = latch1.get()1617    var status→ partial = "partial"18    if (counted == 0) {19      status = "waiting"20    }21    if (remaining == 0) {22      status = "released"23    }2425    println("arrivals=" + arrivals2 + " counted=" + counted2 + " remaining=" + remaining1 + " " + statuspartial)26  }27}
    outputarrivals=2 counted=2 remaining=1 partial
  1. arrivals ← 0, needed ← 3, latch ← 3, counted ← 0, remaining ← 3

    3object Main {4  def main(args: Array[String]): Unit = {5    val arrivals→ 0 = 06    val needed→ 3 = 37    val latch→ 3 = new AtomicInteger(needed3)8    var counted→ 0 = 0910    for (i <- 0 until arrivals) {11      latch.decrementAndGet()12      counted = counted + 113    }1415    val remaining→ 3 = latch3.get()1617    var status→ partial = "partial"18    if (counted == 0) {19      status = "waiting"
  2. status ← waiting

    17var status = "partial"18if (counted0 == 0) {19  status→ waiting = "waiting"20}21if (remaining == 0) {
  3. println("arrivals=" + arrivals + " counted=" + counted + " remaining="…

    25    println("arrivals=" + arrivals0 + " counted=" + counted0 + " remaining=" + remaining3 + " " + statuswaiting)26  }27}
    outputarrivals=0 counted=0 remaining=3 waiting
  1. arrivals ← 3, needed ← 3, latch ← 3, counted ← 0

    3object Main {4  def main(args: Array[String]): Unit = {5    val arrivals→ 3 = 36    val needed→ 3 = 37    val latch→ 3 = new AtomicInteger(needed3)8    var counted→ 0 = 0910    for (i <- 0 until arrivals) {
  2. latch ← 2, counted ← 1

    pass 1 of 3
    10for (i0 <- 0 until arrivals3) {11  latch→ 2.decrementAndGet()12  counted→ 1 = counted + 113}
    All 3 passes — pass 1 is the card above
    passilatchcounted
    103 20 1
    212 11 2
    321 02 3
  3. remaining ← 0, status ← partial

    15val remaining→ 0 = latch0.get()1617var status→ partial = "partial"18if (counted == 0) {19  status = "waiting"
  4. status ← released

    20}21if (remaining0 == 0) {22  status→ released = "released"23}
  5. println("arrivals=" + arrivals + " counted=" + counted + " remaining="…

    25    println("arrivals=" + arrivals3 + " counted=" + counted3 + " remaining=" + remaining0 + " " + statusreleased)26  }27}
    outputarrivals=3 counted=3 remaining=0 released