Como funcionam os mecanismos async e await por baixo do capô?
sobes.tech IA
Resposta da IA
Async/await em Swift baseia-se na concorrência estruturada e utiliza Dispatch/Global Actors. Os mecanismos subjacentes são:
-
Estilo de Continuação: As funções assíncronas são compiladas em estilo de continuações. Em vez de retornarem imediatamente um valor, o controlo é transferido para o runtime Swift, que guarda o estado atual da função (variáveis locais, ponteiro de execução). Quando a operação assíncrona termina, o runtime retoma a execução da função a partir do estado guardado.
-
Tarefa: Cada chamada a uma função
asynccria ou junta-se a umaTaskestruturada. ATaskrepresenta uma unidade de trabalho e forma uma hierarquia. ATaskpai espera que asTaskfilhas terminem. -
Job: A
Taské dividida em unidades de trabalho mais pequenas chamadasJob. UmJobrepresenta um fragmento de código que pode ser executado num executor. -
Executor: O executor é responsável por lançar o
Job. Na biblioteca padrão, usam-seDispatchQueueglobais como executores para a maioria das tarefas assíncronas. Os contextos específicos (por exemplo,MainActor) têm os seus próprios executores especializados. -
Pontos de suspensão:
awaité um ponto de suspensão. Quando atingido, a função é suspensa, o controlo é transferido para o código ou executor que chamou, e oJobatual termina. O runtime Swift guarda o estado da função. -
Reinício: Quando a operação assíncrona esperada com
awaittermina, o runtime Swift cria um novoJobpara continuar a execução da função suspensa. EsteJobé colocado na fila do executor. -
Cancelamento: A concorrência estruturada suporta cancelamento hierárquico. O cancelamento de uma
Taskpai cancela automaticamente todas as suasTaskfilhas. As operações assíncronas podem verificar o estado de cancelamento e reagir em conformidade.
Aqui está um exemplo simplificado da compilação de uma função async:
// Função async original
func fetchData() async -> Data {
// Operação assíncrona
let data = await URLSession.shared.data(from: url).0
return data
}
// Representação simplificada da compilação
// Em vez de retornar, a função aceita uma Continuação
func fetchData(_ continuation: Continuation<Data, Error>) {
// Código inicial da função
let url = URL(string: "...")! // Exemplo
// Iniciar operação assíncrona
URLSession.shared.data(from: url) { data, _, error in
// Este encerramento é executado após a operação assíncrona terminar
if let data = data {
// Passar o resultado para a continuação, retomando a função
continuation.resume(returning: data)
} else if let error = error {
continuation.resume(throwing: error)
} else {
// Tratamento de outros casos
continuation.resume(throwing: NSError(domain: "", code: 0, userInfo: nil))
}
}
// A função termina aqui, aguardando que a chamada a resume da continuação
}
Await é essencialmente açúcar sintático sobre a gestão de Continuation e o planeamento de Job no executor. A suspensão não bloqueia diretamente o thread, mas permite que o executor execute outros Job.