From 5bb3fbc4a536e939bfb761a9a7385f4dca43929e Mon Sep 17 00:00:00 2001 From: stzn Date: Sun, 11 Aug 2024 08:09:16 +0900 Subject: [PATCH 1/4] =?UTF-8?q?textlint=E3=81=AE=E6=8C=87=E6=91=98?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Guide.docc/DataRaceSafety.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Guide.docc/DataRaceSafety.md b/Guide.docc/DataRaceSafety.md index 0d73960..e8a8986 100644 --- a/Guide.docc/DataRaceSafety.md +++ b/Guide.docc/DataRaceSafety.md @@ -41,7 +41,7 @@ Swiftプログラマーは、静的と動的という2つの方法でデータ ### 非隔離(Non-isolated) -関数や変数は、明示的な隔離ドメインの一部である必要はありません。実際、隔離されていないのがデフォルトで、*非隔離(non-isolated)*と呼ばれます。すべてのデータ隔離のルールが適用されるため、非隔離のコードが別のドメインで保護されている状態を変更することはできません。 +関数や変数は、明示的な隔離ドメインの一部である必要はありません。実際、隔離されていないのがデフォルトで、*非隔離(non-isolated)*と呼ばれます。すべてのデータ隔離のルールが適用されるため、非隔離のコードが別のドメインで保護されている状態を変更できません。 ```swift func sailTheSea() { @@ -136,7 +136,7 @@ class ChickenValley { タスクは、プログラム内で並行して実行できる作業の単位です。タスクの外側でSwiftは並行コードを実行できませんが、それは常に手動で開始しなければならないということではありません。一般的に、非同期関数は、それを実行しているタスクを認識する必要はありません。実際、タスクは、多くの場合、アプリケーションフレームワーク内、あるいはプログラムのエントリーポイントといった、より高レベルで開始できます。 -複数のタスクを並行して実行することはできますが、個々のタスクは一度に1つの関数しか実行しません。タスクは、タスク内のコードを最初から最後まで順番に実行します。 +複数のタスクを並行して実行できますが、個々のタスクは一度に1つの関数しか実行しません。タスクは、タスク内のコードを最初から最後まで順番に実行します。 ```swift Task { From e8da091c0fd80e18b06ec94880d0e57e4e73cc0f Mon Sep 17 00:00:00 2001 From: stzn Date: Sun, 11 Aug 2024 08:10:08 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E3=82=AF=E3=83=AD=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=83=A3=E3=81=AE=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88?= =?UTF-8?q?=E3=81=AE=E9=9A=94=E9=9B=A2=E3=81=AE=E6=8C=99=E5=8B=95=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Guide.docc/DataRaceSafety.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/Guide.docc/DataRaceSafety.md b/Guide.docc/DataRaceSafety.md index e8a8986..fd50da5 100644 --- a/Guide.docc/DataRaceSafety.md +++ b/Guide.docc/DataRaceSafety.md @@ -4,8 +4,8 @@ Swiftが用いる基本的な概念について学び、データ競合のない |原文|[https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/dataracesafety](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/dataracesafety)| |---|---| -|更新日|2024/7/24(翻訳を最後に更新した日付)| -|ここまで反映|https://github.com/apple/swift-migration-guide/commit/24e31ffc589fefb42f08877878e689eb29b1644b| +|更新日|2024/8/11(翻訳を最後に更新した日付)| +|ここまで反映|https://github.com/apple/swift-migration-guide/commit/2e7fa65583c1cfc37724c98562bb256ecacb99d8| 従来、可変状態(mutable state)は、細心の注意を払い、ランタイム時の同期によって手動で保護する必要がありました。つまり、ロックやキューなどのツールを使用してデータ競合を防ぐのは、完全にプログラマー任せだということです。これは、正しく実行するだけでなく、ずっと正しく実行し続けることも非常に難しくあります。同期が*必要かどうか*を判断することさえも難しいかもしれません。最悪の状況は、安全でないコードを不正だと検知される保証がないことです。このコードは、多くの場合正しく動いているように見えますが、それはおそらく、データ競合の特徴である間違った予測不可能な挙動が表面化するのに、かなり特殊な条件が必要にだからでしょう。 @@ -227,7 +227,27 @@ protocol Feedable { 隔離の*推論*は、型がそのプロパティとメソッドの隔離を暗黙的に定義することを可能にします。しかし、これらはすべて*宣言*の場合です。隔離の*継承*を用いれば関数の値でも同様の効果を得られます。 -クロージャは、型によって隔離が静的に定義される代わりに、その宣言された場所で隔離をキャプチャできます。このメカニズムは複雑に聞こえるかもしれませんが、実際には非常に自然な振る舞いを可能にします。 +デフォルトでは、クロージャはクロージャを形成したコンテキストと同じコンテキストで隔離されます。例えば、 + +```swift +@MainActor +class Model { ... } + +@MainActor +class C { + var models: [Model] = [] + + func mapModels( + _ keyPath: KeyPath + ) -> some Collection { + models.lazy.map { $0[keyPath: keyPath] } + } +} +``` + +上記のコードでは、`LazySequence.map`のクロージャは`@escaping (Base.Element) -> U`です。このクロージャは、クロージャが元々形成されたメインスレッド上に留まっているはずです。これにより、このクロージャは、それを囲むコンテキストから状態をキャプチャしたり、隔離されたメソッドを呼び出したりできます。元のコンテキストと並行して実行できるクロージャは、後のセクションで説明される`@Sendable`および`sending`アノテーションを通じて明示的に示します。 + +並行に評価される可能性がある`async`クロージャの場合でも、クロージャは元のコンテキストの隔離をキャプチャできます。この仕組みは、`Task`のイニシャライザで使用され、デフォルトではクロージャ内に与えられた操作が元のコンテキストに隔離される一方で、明示的な隔離も指定できます。 ```swift @MainActor @@ -237,10 +257,14 @@ func eat(food: Pineapple) { // クロージャの本体はMainActorの隔離を継承できる Chicken.prizedHen.eat(food: food) } + + Task { @MyGlobalActor in + // このタスクは`MyGlobalActor`に隔離されている + } } ``` -ここでのクロージャの型は`Task.init`によって定義されています。この宣言はどのアクターにも隔離されていませんが、新しく作られるタスクはそれを囲むスコープの `MainActor`による隔離を*継承*します。関数型は、隔離の動作を制御するためのさまざまなメカニズムを提供しますが、デフォルトでは他の型と同じように動作します。 +ここでのクロージャの型は`Task.init`によって定義されています。この宣言はどのアクターにも隔離されていませんが、新しく作られるタスクは、明示的にグローバルアクターを書かない限り、それを囲むスコープの `MainActor`による隔離を*継承*します。関数型は、隔離の動作を制御するためのさまざまなメカニズムを提供しますが、デフォルトでは他の型と同じように動作します。 > 注記: さらに詳細については、The Swift Programming Languageの[Closures][]セクションを参照してください。 From ae835f26ca0d763f018e4b6889f8585539c18102 Mon Sep 17 00:00:00 2001 From: shiz <35151927+stzn@users.noreply.github.com> Date: Sun, 11 Aug 2024 15:41:24 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E3=81=AE=E5=8F=8D=E6=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: SHIMOTORI Shigure --- Guide.docc/DataRaceSafety.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Guide.docc/DataRaceSafety.md b/Guide.docc/DataRaceSafety.md index fd50da5..9c88366 100644 --- a/Guide.docc/DataRaceSafety.md +++ b/Guide.docc/DataRaceSafety.md @@ -41,7 +41,7 @@ Swiftプログラマーは、静的と動的という2つの方法でデータ ### 非隔離(Non-isolated) -関数や変数は、明示的な隔離ドメインの一部である必要はありません。実際、隔離されていないのがデフォルトで、*非隔離(non-isolated)*と呼ばれます。すべてのデータ隔離のルールが適用されるため、非隔離のコードが別のドメインで保護されている状態を変更できません。 +関数や変数は、明示的な隔離ドメインの一部である必要はありません。実際、隔離されていないのがデフォルトで、*非隔離(non-isolated)*と呼ばれます。すべてのデータ隔離のルールが適用されるため、非隔離のコードは別のドメインで保護されている状態を変更できません。 ```swift func sailTheSea() { @@ -245,7 +245,9 @@ class C { } ``` -上記のコードでは、`LazySequence.map`のクロージャは`@escaping (Base.Element) -> U`です。このクロージャは、クロージャが元々形成されたメインスレッド上に留まっているはずです。これにより、このクロージャは、それを囲むコンテキストから状態をキャプチャしたり、隔離されたメソッドを呼び出したりできます。元のコンテキストと並行して実行できるクロージャは、後のセクションで説明される`@Sendable`および`sending`アノテーションを通じて明示的に示します。 +上記のコードでは、`LazySequence.map`のクロージャは`@escaping (Base.Element) -> U`型です。このクロージャは、クロージャが元々形成されたメインアクター上に留まっているはずです。これにより、このクロージャは、それを囲むコンテキストから状態をキャプチャしたり、隔離されたメソッドを呼び出したりできます。 + +元のコンテキストと並行して実行できるクロージャは、後のセクションで説明される`@Sendable`および`sending`アノテーションを通じて明示的に示します。 並行に評価される可能性がある`async`クロージャの場合でも、クロージャは元のコンテキストの隔離をキャプチャできます。この仕組みは、`Task`のイニシャライザで使用され、デフォルトではクロージャ内に与えられた操作が元のコンテキストに隔離される一方で、明示的な隔離も指定できます。 From 475f78cdaf05fb6ff6bfb3a19537ea958485f5c6 Mon Sep 17 00:00:00 2001 From: shiz <35151927+stzn@users.noreply.github.com> Date: Wed, 14 Aug 2024 05:13:10 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E8=AA=A4=E5=AD=97=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Guide.docc/DataRaceSafety.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Guide.docc/DataRaceSafety.md b/Guide.docc/DataRaceSafety.md index 9c88366..74b37e1 100644 --- a/Guide.docc/DataRaceSafety.md +++ b/Guide.docc/DataRaceSafety.md @@ -7,7 +7,7 @@ Swiftが用いる基本的な概念について学び、データ競合のない |更新日|2024/8/11(翻訳を最後に更新した日付)| |ここまで反映|https://github.com/apple/swift-migration-guide/commit/2e7fa65583c1cfc37724c98562bb256ecacb99d8| -従来、可変状態(mutable state)は、細心の注意を払い、ランタイム時の同期によって手動で保護する必要がありました。つまり、ロックやキューなどのツールを使用してデータ競合を防ぐのは、完全にプログラマー任せだということです。これは、正しく実行するだけでなく、ずっと正しく実行し続けることも非常に難しくあります。同期が*必要かどうか*を判断することさえも難しいかもしれません。最悪の状況は、安全でないコードを不正だと検知される保証がないことです。このコードは、多くの場合正しく動いているように見えますが、それはおそらく、データ競合の特徴である間違った予測不可能な挙動が表面化するのに、かなり特殊な条件が必要にだからでしょう。 +従来、可変状態(mutable state)は、細心の注意を払い、ランタイム時の同期によって手動で保護する必要がありました。つまり、ロックやキューなどのツールを使用してデータ競合を防ぐのは、完全にプログラマー任せだということです。これは、正しく実行するだけでなく、ずっと正しく実行し続けることも非常に難しくあります。同期が*必要かどうか*を判断することさえも難しいかもしれません。最悪の状況は、安全でないコードを不正だと検知される保証がないことです。このコードは、多くの場合正しく動いているように見えますが、それはおそらく、データ競合の特徴である間違った予測不可能な挙動が表面化するのに、かなり特殊な条件が必要だからでしょう。 より正確にいうと、データ競合は、あるスレッドがメモリにアクセスしている際に、別のスレッドが同じメモリを変更することで発生します。Swift 6言語モードでは、コンパイル時にデータ競合を防ぐことによってこれらの問題を排除します。