/*:#localized(key: "GuardAgainstReentrancy")
 # How to guard against reentrancy

 The rule: **don't leave a suspension point in the middle of an invariant.**
 Two practical ways to honor it.

 **Keep the check and the change together, with no `await` between them.** Do
 any awaiting *first*, then check-and-mutate in one synchronous run the actor
 can't interrupt:

 ```swift
 func withdraw(_ amount: Int, by name: String) async -> Bool {
     // Do the async work up front...
     try? await Task.sleep(for: .seconds(1))   // e.g. approval

     // ...then check and deduct with NO await between them.
     guard balance >= amount else {
         print("\(name): denied (only \(balance) available)")
         return false
     }
     balance -= amount
     print("\(name): withdrew \(amount), balance now \(balance)")
     return true
 }
 ```

 Now the `guard` and the `balance -= amount` run back-to-back without a
 suspension, so no other task can slip between them. One withdrawal succeeds;
 the other is denied. No overdraft.

 **Or re-check after every `await`.** If you truly must await in the middle,
 re-read the state after you resume and re-validate; never trust a
 pre-`await` snapshot:

 ```swift
 guard balance >= amount else {
     return false
 }
 try? await Task.sleep(for: .seconds(1))
 // Re-check: the balance may have changed while we were suspended.
 guard balance >= amount else {
     print("\(name): denied on re-check")
     return false
 }
 balance -= amount
 ```

 Both approaches share one idea: an actor protects each *individual* access,
 but a **multi-step invariant** ("check, then act") is only safe if no
 suspension splits it. Reentrancy is a feature (it keeps actors from
 deadlocking while they wait), but it means you must reason about what can
 change across each `await`.

 [Previous](@previous)  |  page 5 of 7  |  [Next: Sendable, Briefly](@next)
 */
