Senior
109
questionbank

Как устроены механизмы async и await под капотом?

Получайте ответы на вопросы в реальном времени с Sobes Copilot
Ответ от нейросети sobes.tech

Async/await в Swift построен на основе structured concurrency и использует Dispatch/Global Actors. Под капотом работают следующие механизмы:

  1. Continuation Style: Асинхронные функции компилируются в стиль продолжений. Вместо немедленного возврата значения, управление передается в рантайм Swift, который сохраняет текущее состояние функции (локальные переменные, указатель исполнения). Когда асинхронная операция завершается, рантайм возобновляет выполнение функции с сохраненного состояния.

  2. Task: Каждое вызов async функции создает или присоединяется к структурированной Task. Task представляет единицу работы и формирует иерархию. Родительская Task ожидает завершения дочерних Task.

  3. Job: Task разбивается на более мелкие единицы работы, называемые Job. Job представляет собой фрагмент кода, который может быть выполнен на исполнителе (Executor).

  4. Executor: Исполнитель отвечает за запуск Job. В стандартной библиотеке используются глобальные DispatchQueue как исполнители для большинства асинхронных задач. Специфические контексты (например, MainActor) имеют свои специализированные исполнители.

  5. Suspension Points: await является точкой приостановки (suspension point). При достижении await, функция приостанавливается, управление передается вызывающему коду или исполнителю, а текущий Job завершается. Рантайм Swift сохраняет состояние функции.

  6. Resumption: Когда асинхронная операция, на которую ожидал await, завершается, рантайм Swift создает новый Job для продолжения выполнения приостановленной функции. Этот Job ставится в очередь на исполнитель.

  7. Cancellation: Structured concurrency поддерживает иерархическую отмену. Отмена родительской Task автоматически отменяет все ее дочерние Task. Асинхронные операции могут проверять статус отмены и реагировать соответствующим образом.

Вот упрощенный пример компиляции async функции:

swift

Await по сути является синтаксическим сахаром над управлением Continuation и планированием Job на исполнителе. Приостановка не блокирует поток напрямую, а позволяет исполнителю выполнять другие Job.