Record shared read permits against a fixed pool and report the access mode.

bounded permit pool A coordination report can record how a shared pool is occupied. An `AtomicInteger` started at the slot count models a pool of shared read permits, and a `getAndDecrement` that returns a positive prior value takes one permit without blocking; a draw past the last permit is returned with `getAndIncrement`. With no permits taken the pool is writable for an exclusive writer, with one permit taken access is single, and with every permit taken access is fully shared. The status line summarizes the mode, and `get` reports the free permits.

Permit Pool Coordination Report

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

object Main {
  def main(args: Array[String]): Unit = {
    val readers = 1
    val slots = 3
    val permits = new AtomicInteger(slots)
    var held = 0

    for (i <- 0 until readers) {
      if (permits.getAndDecrement() > 0) {
        held = held + 1
      } else {
        permits.getAndIncrement()
      }
    }

    val free = permits.get()

    var status = "single"
    if (held == 0) {
      status = "writable"
    }
    if (held == slots) {
      status = "shared"
    }

    println("readers=" + readers + " held=" + held + " free=" + free + " " + status)
  }
}
import java.util.concurrent.atomic.AtomicInteger

object Main {
  def main(args: Array[String]): Unit = {
    val readers = 0
    val slots = 3
    val permits = new AtomicInteger(slots)
    var held = 0

    for (i <- 0 until readers) {
      if (permits.getAndDecrement() > 0) {
        held = held + 1
      } else {
        permits.getAndIncrement()
      }
    }

    val free = permits.get()

    var status = "single"
    if (held == 0) {
      status = "writable"
    }
    if (held == slots) {
      status = "shared"
    }

    println("readers=" + readers + " held=" + held + " free=" + free + " " + status)
  }
}
import java.util.concurrent.atomic.AtomicInteger

object Main {
  def main(args: Array[String]): Unit = {
    val readers = 3
    val slots = 3
    val permits = new AtomicInteger(slots)
    var held = 0

    for (i <- 0 until readers) {
      if (permits.getAndDecrement() > 0) {
        held = held + 1
      } else {
        permits.getAndIncrement()
      }
    }

    val free = permits.get()

    var status = "single"
    if (held == 0) {
      status = "writable"
    }
    if (held == slots) {
      status = "shared"
    }

    println("readers=" + readers + " held=" + held + " free=" + free + " " + status)
  }
}
  1. readers ← 1, slots ← 3, permits ← 3, held ← 0

    3object Main {4  def main(args: Array[String]): Unit = {5    val readers→ 1 = 1 //@readers=0, 36    val slots→ 3 = 37    val permits→ 3 = new AtomicInteger(slots3)8    var held→ 0 = 0910    for (i <- 0 until readers) {
  2. for (i <- 0 until readers)

    10for (i0 <- 0 until readers1) {11  if (permits.getAndDecrement() > 0) {
  3. held ← 1

    10for (i <- 0 until readers) {11  if (permits2.getAndDecrement() > 0) {12    held→ 1 = held + 113  } else {14    permits.getAndIncrement()
  4. free ← 2, status ← single

    18    val free→ 2 = permits2.get()1920    var status→ single = "single"21    if (held == 0) {22      status = "writable"23    }24    if (held == slots) {25      status = "shared"26    }2728    println("readers=" + readers1 + " held=" + held1 + " free=" + free2 + " " + statussingle)29  }30}
    outputreaders=1 held=1 free=2 single
  1. readers ← 0, slots ← 3, permits ← 3, held ← 0, free ← 3, status ← single

    3object Main {4  def main(args: Array[String]): Unit = {5    val readers→ 0 = 06    val slots→ 3 = 37    val permits→ 3 = new AtomicInteger(slots3)8    var held→ 0 = 0910    for (i <- 0 until readers) {11      if (permits.getAndDecrement() > 0) {12        held = held + 113      } else {14        permits.getAndIncrement()15      }16    }1718    val free→ 3 = permits3.get()1920    var status→ single = "single"21    if (held == 0) {22      status = "writable"
  2. status ← writable

    20var status = "single"21if (held0 == 0) {22  status→ writable = "writable"23}24if (held == slots) {
  3. println("readers=" + readers + " held=" + held + " free=" + free + " "…

    28    println("readers=" + readers0 + " held=" + held0 + " free=" + free3 + " " + statuswritable)29  }30}
    outputreaders=0 held=0 free=3 writable
  1. readers ← 3, slots ← 3, permits ← 3, held ← 0

    3object Main {4  def main(args: Array[String]): Unit = {5    val readers→ 3 = 36    val slots→ 3 = 37    val permits→ 3 = new AtomicInteger(slots3)8    var held→ 0 = 0910    for (i <- 0 until readers) {
  2. for (i <- 0 until readers)

    pass 1 of 3
    10for (i0 <- 0 until readers3) {11  if (permits.getAndDecrement() > 0) {
    All 3 passes — pass 1 is the card above
    passi
    10
    21
    32
  3. held ← 1

    pass 1 of 3
    10for (i <- 0 until readers) {11  if (permits2.getAndDecrement() > 0) {12    held→ 1 = held + 113  } else {14    permits.getAndIncrement()
    All 3 passes — pass 1 is the card above
    passpermitsheld
    120 1
    211 2
    302 3
  4. free ← 0, status ← single

    18val free→ 0 = permits0.get()1920var status→ single = "single"21if (held == 0) {22  status = "writable"
  5. status ← shared

    23}24if (held3 == slots3) {25  status→ shared = "shared"26}
  6. println("readers=" + readers + " held=" + held + " free=" + free + " "…

    28    println("readers=" + readers3 + " held=" + held3 + " free=" + free0 + " " + statusshared)29  }30}
    outputreaders=3 held=3 free=0 shared