Grant nonblocking requests against a fixed permit pool and report the remaining capacity.

semaphore permits A `threading.Semaphore` hands out a bounded number of permits, so the permits still available describe how much shared capacity remains.

Semaphore Capacity Coordination Report

requests
semaphore_capacity_coordination_report.py
Replay: real traced execution (multi-file project)
import threading


requests = 2
permits = threading.Semaphore(3)
granted = 0

for _ in range(requests):
    if permits.acquire(blocking=False):
        granted += 1

available = 3 - granted
status = "full" if available == 0 else "tight" if available <= 1 else "open"

print("requests=" + str(requests) + " granted=" + str(granted) + " available=" + str(available) + " status=" + status)
import threading


requests = 0
permits = threading.Semaphore(3)
granted = 0

for _ in range(requests):
    if permits.acquire(blocking=False):
        granted += 1

available = 3 - granted
status = "full" if available == 0 else "tight" if available <= 1 else "open"

print("requests=" + str(requests) + " granted=" + str(granted) + " available=" + str(available) + " status=" + status)
import threading


requests = 3
permits = threading.Semaphore(3)
granted = 0

for _ in range(requests):
    if permits.acquire(blocking=False):
        granted += 1

available = 3 - granted
status = "full" if available == 0 else "tight" if available <= 1 else "open"

print("requests=" + str(requests) + " granted=" + str(granted) + " available=" + str(available) + " status=" + status)
  1. requests ← 2, permits ← <threading.Semaphore at ⟨addr A⟩: value=3>

    4requests→ 2 = 2  #@requests=0, 35permits→ <threading.Semaphore at ⟨addr A⟩: value=3> = threading<module 'threading' from '/usr/local/lib/python3.12/threading.py'>.Semaphore(3)6granted→ 0 = 0
  2. for _ in range(requests):

    pass 1 of 2
    8for _0 in range(requests2):9    if permits.acquire(blocking=False):10        granted += 1
  3. granted ← 1

    pass 1 of 2
    8for _ in range(requests):9    if permits<threading.Semaphore at ⟨addr A⟩: value=2>.acquire(blocking=False):10        granted→ 1 += 1
  4. for _ in range(requests):

    pass 2 of 2
    8for _1 in range(requests2):9    if permits.acquire(blocking=False):10        granted += 1
  5. granted ← 2

    pass 2 of 2
    8for _ in range(requests):9    if permits<threading.Semaphore at ⟨addr A⟩: value=1>.acquire(blocking=False):10        granted→ 2 += 1
  6. available ← 1, status ← tight

    12available→ 1 = 3 - granted213status→ tight = "full" if available1 == 0 else "tight" if available <= 1 else "open"1415print("requests=" + str(requests2) + " granted=" + str(granted2) + " available=" + str(available1) + " status=" + statustight)
    outputrequests=2 granted=2 available=1 status=tight
  1. requests ← 0, permits ← <threading.Semaphore at ⟨addr A⟩: value=3>

    4requests→ 0 = 05permits→ <threading.Semaphore at ⟨addr A⟩: value=3> = threading<module 'threading' from '/usr/local/lib/python3.12/threading.py'>.Semaphore(3)6granted→ 0 = 078for _ in range(requests):9    if permits.acquire(blocking=False):10        granted += 11112available→ 3 = 3 - granted013status→ open = "full" if available3 == 0 else "tight" if available <= 1 else "open"1415print("requests=" + str(requests0) + " granted=" + str(granted0) + " available=" + str(available3) + " status=" + statusopen)
    outputrequests=0 granted=0 available=3 status=open
  1. requests ← 3, permits ← <threading.Semaphore at ⟨addr A⟩: value=3>

    4requests→ 3 = 35permits→ <threading.Semaphore at ⟨addr A⟩: value=3> = threading<module 'threading' from '/usr/local/lib/python3.12/threading.py'>.Semaphore(3)6granted→ 0 = 0
  2. for _ in range(requests):

    pass 1 of 3
    8for _0 in range(requests3):9    if permits.acquire(blocking=False):10        granted += 1
    All 3 passes — pass 1 is the card above
    pass_
    10
    21
    32
  3. granted ← 1

    pass 1 of 3
    8for _ in range(requests):9    if permits<threading.Semaphore at ⟨addr A⟩: value=2>.acquire(blocking=False):10        granted→ 1 += 1
    All 3 passes — pass 1 is the card above
    passpermitsgranted
    1<threading.Semaphore at ⟨addr A⟩: value=2>0 1
    2<threading.Semaphore at ⟨addr A⟩: value=1>1 2
    3<threading.Semaphore at ⟨addr A⟩: value=0>2 3
  4. available ← 0, status ← full

    12available→ 0 = 3 - granted313status→ full = "full" if available0 == 0 else "tight" if available <= 1 else "open"1415print("requests=" + str(requests3) + " granted=" + str(granted3) + " available=" + str(available0) + " status=" + statusfull)
    outputrequests=3 granted=3 available=0 status=full