/*:#localized(key: "MainActorMainThread")
 # `@MainActor`: the main thread, checked by the compiler

 UI state must only ever be touched on the main thread. The classic way to honor
 that rule was to wrap every update in `DispatchQueue.main.async` and *hope* you
 never forgot. `@MainActor` does the job for you: mark a type `@MainActor` and
 every one of its methods is **guaranteed** to run on the main thread, no matter
 who calls it, and the compiler checks it.

 To watch that guarantee do real work, we deliberately start on a **background
 thread** with `Task.detached`, then call into a `@MainActor` display. A small
 helper reports whether we are on the main thread, because Swift won't let you
 read `Thread.isMainThread` *directly* inside an async task: a task can hop
 threads, so a bare reading would be unreliable.
 */
//#-editable-code
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

// Read the thread through a synchronous helper, so it is safe to call from a task.
func runningOnMainThread() -> Bool {
    Thread.isMainThread
}

@MainActor
final class BalanceDisplay {
    private(set) var balance = 0

    func deposit(_ amount: Int) {
        balance += amount
        print("Deposited \(amount), balance now \(balance). On main thread? \(runningOnMainThread())")
    }
}

let display = BalanceDisplay()

// Task.detached starts on a background thread instead of the main one.
Task.detached {
    print("Starting the deposits. On main thread? \(runningOnMainThread())")
    await display.deposit(100)
    await display.deposit(50)
    PlaygroundPage.current.finishExecution()
}
//#-end-editable-code
/*:#localized(key: "MainActorMainThreadNotice")
 Read the output top to bottom. The first line prints `false`: we really are on a
 background thread. Every `deposit` line prints `true`: `@MainActor` pulled that
 work onto the main thread for us. We started off main, yet the display was only
 ever touched on main, and we never wrote `DispatchQueue.main.async` once. That is
 the whole promise of `@MainActor`.

 You did have to write `await` before each `deposit`. That is what the next page
 is about.

 * callout(Try it): Change `Task.detached` to a plain `Task`. A plain `Task`
 inherits the page's context, which is the main actor, so now even the first line
 prints `true`: there was never a background thread to leave. `Task.detached` is
 what put us on one.

 [Previous](@previous)  |  page 2 of 11  |  [Next: Crossing Onto MainActor](@next)
 */
