Ako fungujú mechanizmy async a await na pozadí?
sobes.tech AI
Odpoveď od AI
Async/await v Swifte je postavený na štruktúrovanej konkurencii a využíva Dispatch/Global Actors. Mechanizmy, ktoré bežia na pozadí, sú:
-
Štýl pokračovania: Asynchrónne funkcie sú kompilované do štýlu pokračovania. Namiesto okamžitého vrátenia hodnoty sa riadenie prenáša na Swift runtime, ktorý uloží aktuálny stav funkcie (lokálne premenné, ukazovateľ vykonávania). Keď asynchrónna operácia skončí, runtime obnoví vykonávanie funkcie zo stavu, ktorý bol uložený.
-
Task: Každé volanie
asyncfunkcie vytvorí alebo sa pripojí ku štruktúrovanejTask.Taskpredstavuje jednotku práce a tvorí hierarchiu. RodičovskýTaskčaká na dokončenie dcérskychTask. -
Job:
Tasksa rozdeľuje na menšie jednotky práce, nazývanéJob.Jobpredstavuje fragment kódu, ktorý môže byť vykonaný na vykonávateľovi (Executor). -
Executor: Vykonávateľ je zodpovedný za spustenie
Job. V štandardnej knižnici sa používajú globálneDispatchQueueako vykonávateľov pre väčšinu asynchrónnych úloh. Špeciálne kontexty (napríkladMainActor) majú svoje špecializované vykonávateľov. -
Bodky pozastavenia:
awaitje bod pozastavenia (suspension point). Pri dosiahnutíawaitsa funkcia pozastaví, riadenie sa prenesie na volajúci kód alebo vykonávateľa, a aktuálnyJobsa ukončí. Swift runtime uloží stav funkcie. -
Obnovenie: Keď asynchrónna operácia, na ktorú
awaitčakal, skončí, Swift runtime vytvorí novýJobna pokračovanie vykonávania pozastavenej funkcie. TentoJobsa umiestni do fronty na vykonávateľovi. -
Zrušenie: Štruktúrovaná konkurencia podporuje hierarchické zrušenie. Zrušenie rodičovského
Taskautomaticky zruší všetky jeho dcérskeTask. Asynchrónne operácie môžu kontrolovať stav zrušenia a reagovať primerane.
Tu je zjednodušený príklad kompilácie async funkcie:
// Počiatočná async funkcia
func fetchData() async -> Data {
// Asynchrónna operácia
let data = await URLSession.shared.data(from: url).0
return data
}
// Zjednodušené zobrazenie kompilácie
// Namiesto návratu funkcia prijíma Continuation
func fetchData(_ continuation: Continuation<Data, Error>) {
// Počiatočný kód funkcie
let url = URL(string: "...")! // Príklad
// Spustenie asynchrónnej operácie
URLSession.shared.data(from: url) { data, _, error in
// Tento blok sa vykoná po dokončení asynchrónnej operácie
if let data = data {
// Prenos výsledku do continuation, obnovenie funkcie
continuation.resume(returning: data)
} else if let error = error {
continuation.resume(throwing: error)
} else {
// Spracovanie iných prípadov
continuation.resume(throwing: NSError(domain: "", code: 0, userInfo: nil))
}
}
// Funkcia končí tu, čaká na volanie resume od continuation
}
Await je v podstate syntaktický cukor nad správou Continuation a plánovaním Job na vykonávateľovi. Pozastavenie neblokuje priamo vlákno, ale umožňuje vykonávateľovi vykonávať iné Job-y.