Jak fungují mechanismy async a await na pozadí?
sobes.tech AI
Odpověď od AI
Async/await ve Swiftu je postaven na strukturované konkurenci a využívá Dispatch/Global Actors. Mechanismy, které běží na pozadí, jsou:
-
Styl pokračování: Asynchronní funkce jsou kompilovány do stylu pokračování. Místo okamžitého vrácení hodnoty se řízení předává runtime Swift, který ukládá aktuální stav funkce (lokální proměnné, ukazatel vykonávání). Když asynchronní operace skončí, runtime obnoví vykonávání funkce ze stavu, který byl uložen.
-
Task: Každé volání
asyncfunkce vytvoří nebo se připojí ke strukturovanémuTask.Taskpředstavuje jednotku práce a vytváří hierarchii. RodičovskýTaskčeká na dokončení podřízenýchTask. -
Job:
Taskje rozdělen na menší jednotky práce nazývanéJob.Jobpředstavuje fragment kódu, který může být vykonán na vykonavateli (Executor). -
Executor: Vykonavatel je zodpovědný za spuštění
Job. Ve standardní knihovně jsou jako vykonavatelé používány globálníDispatchQueuepro většinu asynchronních úloh. Specifické kontexty (napříkladMainActor) mají své specializované vykonavatele. -
Suspension Points:
awaitje bod pozastavení (suspension point). Při dosaženíawaitse funkce pozastaví, řízení se předá volajícímu kódu nebo vykonavateli a aktuálníJobse ukončí. Runtime Swift uloží stav funkce. -
Resumption: Když asynchronní operace, na kterou
awaitčekal, skončí, runtime Swift vytvoří novýJobpro pokračování vykonávání pozastavené funkce. TentoJobje zařazen do fronty na vykonavateli. -
Cancellation: Strukturovaná konkurence podporuje hierarchické zrušení. Zrušení rodičovského
Taskautomaticky zruší všechny její podřízenéTask. Asynchronní operace mohou kontrolovat stav zrušení a reagovat odpovídajícím způsobem.
Zde je zjednodušený příklad kompilace async funkce:
// Výchozí async funkce
func fetchData() async -> Data {
// Asynchronní operace
let data = await URLSession.shared.data(from: url).0
return data
}
// Zjednodušené zobrazení kompilace
// Místo návratu funkce přijímá Continuation
func fetchData(_ continuation: Continuation<Data, Error>) {
// Počáteční kód funkce
let url = URL(string: "...")! // Příklad
// Spuštění asynchronní operace
URLSession.shared.data(from: url) { data, _, error in
// Tento blok se provádí po dokončení asynchronní operace
if let data = data {
// Předání výsledku do continuation, obnovení funkce
continuation.resume(returning: data)
} else if let error = error {
continuation.resume(throwing: error)
} else {
// Zpracování jiných případů
continuation.resume(throwing: NSError(domain: "", code: 0, userInfo: nil))
}
}
// Funkce končí zde, čeká na volání resume od continuation
}
Await je v podstatě syntaktický cukr nad správou Continuation a plánováním Job na vykonavateli. Pozastavení přímo nezablokuje vlákno, ale umožňuje vykonavateli vykonávat jiné Job.