/*:#localized(key: "DispatchSemaphoreLimiting")
 # `DispatchSemaphore`: limiting how many run at once

 A group answers "are they *all* done?" A semaphore answers a different
 question: "how many are allowed *at once*?"

 A **`DispatchSemaphore`** is a counter of available permits. You create it
 with a starting count. `wait()` takes one permit, blocking if none are left;
 `signal()` returns a permit. When the count is, say, 2, only two tasks can
 hold a permit at the same time; everyone else waits their turn.

 Picture the coffee bar with five baristas but a **single espresso machine
 that seats two portafilters**. Only two shots can pull at once.
 */
//#-editable-code
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

let machine = DispatchSemaphore(value: 2)     // two slots on the machine
let group = DispatchGroup()
let floor = DispatchQueue(label: "floor", attributes: .concurrent)

for name in ["Ana", "Ben", "Cy", "Dee", "Eli"] {
    group.enter()
    floor.async {
        machine.wait()                        // take a slot (waits if full)
        print("→ \(name) starts pulling a shot")
        Thread.sleep(forTimeInterval: 0.5)
        print("←   \(name) done, frees the machine")
        machine.signal()                      // give the slot back
        group.leave()
    }
}

group.notify(queue: .main) {
    print("☕️ Every shot pulled")
    PlaygroundPage.current.finishExecution()
}
//#-end-editable-code
/*:#localized(key: "DispatchSemaphoreLimiting-2")
 Notice this uses **both** tools together: the semaphore caps concurrency at
 two, the group tells you when all five are finished.

 **Watch it run:** you'll never see more than two `→ starts` without a `← done`
 in between. The output comes in waves: two baristas start, two finish, the
 next two start, and so on. The exact names in each wave can vary between runs,
 but the **rule never breaks**: at most two shots pull simultaneously.

 * callout(Try it): Change `value: 2` to `value: 1` and the whole thing goes
 strictly one-at-a-time. Change it to `5` and everyone starts at once. That
 single number is the throttle.

 [Previous](@previous)  |  page 6 of 8  |  [Next: A Semaphore of 1 as a Lock](@next)
 */
