/*:#localized(key: "ActorIsolation")
 # Actor isolation: `await` outside, synchronous inside

 Look again at how we read the balance from outside: `await ledger.balance`.
 Why the `await`?

 Because the actor might be **busy**. When you call an actor's method or read
 its mutable state **from outside**, your task may have to wait for whoever is
 currently inside to finish. That possible wait is a suspension point, and in
 Swift every suspension point is marked with `await`. This is **actor
 isolation**: the actor's mutable state is *isolated* to the actor, and
 outsiders reach it only through `await`.

 Inside the actor, it's different. Code running *within* the actor already
 holds the actor to itself, so it touches its own state **synchronously**, no
 `await`.
 */
//#-editable-code
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

actor Ledger {
    private(set) var balance = 0

    func deposit(_ amount: Int) {
        balance += amount   // inside: synchronous, no await
        report()            // calling another method on self: no await
    }

    private func report() {
        print("Balance is now \(balance)")   // inside: synchronous
    }
}

let ledger = Ledger()

Task {
    await ledger.deposit(50)   // outside: await required
    await ledger.deposit(25)   // outside: await required
    let current = await ledger.balance
    print("Read from outside: \(current)")
    PlaygroundPage.current.finishExecution()
}
//#-end-editable-code
/*:#localized(key: "ActorIsolation-2")
 **Watch it run:** you'll see `Balance is now 50`, `Balance is now 75`, then
 `Read from outside: 75`. Notice the pattern: **every** access from the `Task`
 needed `await`; nothing inside `deposit` or `report` did. Inside the actor,
 you're already at the front of the line.

 ---
 
 ## `nonisolated` for state that doesn't need protecting

 Not everything in an actor touches mutable state. An immutable `let` never
 changes, so reading it can't race; there's no reason to make callers `await`
 it. Mark such members **`nonisolated`** to opt them out of isolation:

 ```swift
 actor Account {
     let owner: String   // immutable, safe to read anytime
     private(set) var balance: Int

     init(owner: String, balance: Int) {
         self.owner = owner
         self.balance = balance
     }

     nonisolated var label: String {
         "Account for \(owner)"   // only reads the immutable `owner`
     }

     func deposit(_ amount: Int) {
         balance += amount
     }
 }

 let account = Account(owner: "Robin", balance: 100)
 print(account.label)   // no await, it's nonisolated
 ```

 Because `label` only reads the immutable `owner`, it's declared `nonisolated`
 and you call it like a normal property, no `await`, no waiting. The catch: a
 `nonisolated` member **may not touch the actor's mutable state**. Try to read
 `balance` from inside `label` and the compiler rejects it, because that access
 *would* need protecting. That error is the isolation rules keeping you honest.

 > If you added `balance` to the `label` string above, the
 > compiler would reject the code right there, because `nonisolated` members may
 > not touch isolated state. That error is the isolation rule working as
 > intended, not a bug in your code.

 [Previous](@previous)  |  page 3 of 7  |  [Next: Reentrancy](@next)
 */
