Sobes.tech
Senior

Kā darbojas async un await mehānismi aizkulisēs?

sobes.tech AI

Atbilde no AI

Swift valodā Async/await ir balstīts uz strukturētu konkūrenci un izmanto Dispatch/Global Actors. Zem virsmas darbojas šādi mehānismi:

  1. Turpinājuma stils: Asinhronās funkcijas tiek kompilētas uz turpinājumu stila. Tā vietā, lai nekavējoties atgrieztu vērtību, vadība tiek nodota Swift laikam, kas saglabā pašreizējo funkcijas stāvokli (lokālos mainīgos, izpildes rādītāju). Kad asinhronā operācija beidzas, laika pārvaldnieks atsāk funkcijas izpildi no saglabātā stāvokļa.

  2. Uzdevums: Katrs async funkcijas izsaukums izveido vai pievienojas strukturētajam Task. Task pārstāv darba vienību un veido hierarhiju. Vecāku Task gaida, kamēr bērnu Task ir pabeigti.

  3. Darbs: Task tiek sadalīts mazākās darba vienībās, sauktas par Job. Job ir koda fragments, ko var izpildīt izpildītājā (Executor).

  4. Izpildītājs: Izpildītājs ir atbildīgs par Job izpildi. Standarta bibliotēkā galvenokārt tiek izmantoti globālie DispatchQueue kā izpildītāji lielākajai daļai asinhrono uzdevumu. Konkrēti konteksti (piemēram, MainActor) izmanto savus specializētos izpildītājus.

  5. Apturēšanas punkti: await ir apturēšanas punkts. Sasniedzot await, funkcija tiek apturēta, vadība tiek nodota izsaucējam vai izpildītājam, un pašreizējais Job tiek pabeigts. Swift laikam tiek saglabāts funkcijas stāvoklis.

  6. Atsākšana: Kad asinhronā operācija, uz kuru tika gaidīts ar await, beidzas, Swift laikam izveido jaunu Job funkcijas turpināšanai. Šis Job tiek pievienots izpildītāja rindai.

  7. Atcelšana: Strukturētā konkūrence atbalsta hierarhisku atcelšanu. Vecāku Task atcelšana automātiski atceļ visus tās bērnu Task. Asinhronās operācijas var pārbaudīt atcelšanas statusu un atbilstoši reaģēt.

Šeit ir vienkāršots piemērs async funkcijas kompilācijai:

// Izcila async funkcija
func fetchData() async -> Data {
    // Asinhronā operācija
    let data = await URLSession.shared.data(from: url).0
    return data
}

// Vienkāršota kompilācijas attēlojums
// Tā vietā, lai atgrieztu, funkcija pieņem Continuation
func fetchData(_ continuation: Continuation<Data, Error>) {
    // Funkcijas sākuma kods
    let url = URL(string: "...")! // Piemērs
    
    // Asinhronās operācijas uzsākšana
    URLSession.shared.data(from: url) { data, _, error in
        // Šis aizkaves izpildās pēc asinhronās operācijas pabeigšanas
        if let data = data {
            // Nodod rezultātu uz turpinājumu, atsākot funkciju
            continuation.resume(returning: data)
        } else if let error = error {
            continuation.resume(throwing: error)
        } else {
            // Citu gadījumu apstrāde
            continuation.resume(throwing: NSError(domain: "", code: 0, userInfo: nil))
        }
    }
    // Funkcija šeit beidzas, gaidot `resume` izsaukumu no turpinājuma
}

Await būtībā ir sintakses cukurs pār Continuation pārvaldību un Job plānošanu izpildītājā. Apturēšana tieši ne bloķē pavedienu, bet ļauj izpildītājam izpildīt citus Job.