こんにちは、クラシル開発部で iOS エンジニアをしている @inamiy です。

この記事は dely AdventCalendar 2021 24日目の記事です。

https://adventar.org/calendars/6455/embed

今日は、Swift 5.5 から導入された Swift Concurrency (Swift 並行処理) について解説しつつ、アクターモデルを活用したアプリの状態管理アーキテクチャーについて取り上げてみたいと思います。

なお、今回の記事は Swift に詳しくない方でも Swift Concurrency の良さが伝わるように書いてみたので、普段より文字数が多い読み物になっています。

Swift Concurrency のおさらい

まずはじめに、Swift 言語に馴染みのない方向けに、Swift Concurrency の簡単な解説をします。

Swift Concurrency とは、Swift の並行処理全般について言語仕様レベルから機能拡張したもので、大きく分けて次の3つの要素から成ります。

  1. async / await
  2. Structured Concurrency
  3. Actors

Concurrency - The Swift Programming Language (Swift 5.5)

Swiftの並行処理について - 見つける - Apple Developer

1. async / await

async / await は、近年のモダンなプログラミング言語の多くで採用されているおなじみの構文です。 Promise / Future(非同期計算の結果を返す)に相当する非同期計算を async 関数として宣言し、手続き的に書くことができます。また、非同期イテレーターを担う AsyncSequencefor await 文をサポートします。

内部的には**「継続 (continuation) を用いたコルーチン(協調的スレッドプール)」**を並行処理ランタイム上で実現しており、work-stealing な M:N スケジューラーが待機中のスレッドに次の計算(継続)を効率良く割り当てます。これは従来のスレッドによる非同期処理と大きく異なり、 async 関数の中で await をしても、スレッドそのものをブロッキング状態にすることなく、次の手順を行います:

  1. 中断:非同期計算の中断ポイント ( await ) で、ローカル変数等のスタック情報を一時的にヒープに退避し、他のタスクにスレッドを譲る