Exercise: Counting Semaphore
This exercise puts the contention and bounded-resource lesson into code.
Scenario
Model a resource pool whose total permit count is set by an init command. The pool tracks
how many permits are currently free. acquire takes one permit if any are available; if
none remain, the caller is reported as blocked. release returns one permit, but never
lets the free count exceed the pool total. Commands arrive one at a time in a single
thread — this is a deterministic simulation of the semaphore protocol, not actual concurrent
execution.
Commands
| Command | Behavior | Output |
|---|---|---|
["init", n] | Create the pool with n total permits, all free | "Pool: <n> permits" |
["acquire", who] | Take one permit if free count is above zero | "<who> acquired (<free> left)", or "<who> blocked (0 left)" if no permits remain |
["release", who] | Return one permit if the pool is not already full | "<who> released (<free> left)", or "release ignored (<free> left)" if the pool was already at full capacity |
["free"] | Report the current free count | "Free: <free>" |
The first command in every test is always init. The free count in the output reflects the
state after the operation completes.
7 init 2 acquire Alice acquire Bob acquire Carol free release Alice release Alice
Pool: 2 permits Alice acquired (1 left) Bob acquired (0 left) Carol blocked (0 left) Free: 0 Alice released (1 left) Alice released (2 left)
The pool starts with 2 permits. Alice acquires one, leaving 1 free. Bob acquires the last one, leaving 0 free. Carol tries to acquire but the pool is exhausted and is blocked; the free count stays at 0. free confirms 0 permits remain. Alice releases, bringing the count to 1. Alice releases again — even though Alice already released, the pool is not yet full — so the count goes to 2, the original total. The second release is not ignored because the pool was not yet back to its full 2 permits.
Your task
Implement the skeleton in the editor below so the commands produce the output described above.