Skip to content

Commit 1290711

Browse files
authored
Merge pull request #613 from stzn/noasync
noasyncの説明を追加
2 parents 21b679b + 1668a01 commit 1290711

File tree

4 files changed

+61
-8
lines changed

4 files changed

+61
-8
lines changed

language-guide/concurrency.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 並行処理\(Concurrency\)
22

3-
最終更新日: 2025/02/01
3+
最終更新日: 2025/02/22
44
原文: https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html
55

66
非同期操作を行う。
@@ -379,7 +379,7 @@ extension TemperatureLogger {
379379

380380
上のコードでは、測定値の配列を一度に 1 つずつ変換しています。map 操作の進行中、いくつかの温度は華氏で、他の温度は摂氏です。しかし、どのコードにも `await` が含まれていないため、このメソッドには潜在的な中断ポイントがありません。このメソッドが変更する状態はアクターに属し、そのアクター上ではないコードが読んだり変更することから保護されています。つまり、単位変換の進行中に、他のコードが部分的に変換された温度のリストを読む方法がないということです。
381381

382-
潜在的な中断ポイントをなくすことで一時的な不正状態から保護されているアクター内にコードを書くことに加えて、そのコードを同期メソッドに移すことができます。上記の `convertFahrenheitToCelsius()` メソッドは同期メソッドなので、潜在的な中断ポイントを含まないことが保証されています。この関数は、一時的にデータモデルの一貫性を失わせるコードをカプセル化し、データの一貫性を取り戻す前に他のコードが実行できないようにして作業を完了させることを、コードを読んだ人が簡単に認識できるようにします。将来、この関数に並行コードを追加して、潜在的な中断ポイントを導入しようとすると、バグを導入する代わりにコンパイル時エラーが発生します
382+
潜在的な中断ポイントをなくすことで一時的な不正状態から保護されているアクター内にコードを書くことに加えて、そのコードを同期メソッドに移すことができます。上記の `convertFahrenheitToCelsius()` メソッドは同期メソッドなので、潜在的な中断ポイントを含まないことが保証されています。この関数は、一時的にデータモデルの一貫性を失わせるコードをカプセル化し、データの一貫性を取り戻す前に他のコードが実行できないようにして作業を完了させることを、コードを読んだ人が簡単に認識できるようにします。将来、この関数に並行コードを追加して、潜在的な中断ポイントを導入しようとすると、バグを導入する代わりにコンパイルエラーが発生します
383383

384384
## <a id="sendable-types">`Sendable`\(Sendable Types\)</a>
385385

language-guide/macros.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# マクロ\(Macros\)
22

3-
最終更新日: 2024/04/19
3+
最終更新日: 2025/02/22
44
原文: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/macros
55

66
コンパイル時にコードを生成するためにマクロを使用します。
@@ -317,7 +317,7 @@ struct MyProjectMacros: CompilerPlugin {
317317

318318
`#fourCharacterCode` マクロを展開するために、Swift はこのマクロを使用するコードの AST を、マクロの実装を含むライブラリに送信します。ライブラリの中で、Swift はメソッドの引数として AST とコンテキストを渡して `FourCharacterCode.expansion(of:in:)` を呼び出します。`expansion(of:in:)` の実装は、`#fourCharacterCode` に引数として渡された文字列を見つけ、対応する 32 ビット符号なし整数リテラルの値を計算します。
319319

320-
上記の例では、最初の `guard` ブロックが AST から文字列リテラルを取り出し、その AST 要素を `literalSegment` に代入しています。2 番目の `guard` ブロックは、private な `fourCharacterCode(for:)` 関数を呼び出します。これらのブロックはいずれも、マクロの使い方が間違っているとエラーを発生させます(エラーメッセージは、不正な呼び出し先でのコンパイラエラーになります)。例えば、マクロを `#fourCharacterCode("AB" + "CD")` として呼び出そうとすると、コンパイラは「静的な文字列が必要です(Need a static string)」というエラーを表示します。
320+
上記の例では、最初の `guard` ブロックが AST から文字列リテラルを取り出し、その AST 要素を `literalSegment` に代入しています。2 番目の `guard` ブロックは、private な `fourCharacterCode(for:)` 関数を呼び出します。これらのブロックはいずれも、マクロの使い方が間違っているとエラーを発生させます(エラーメッセージは、不正な呼び出し先でのコンパイルエラーになります)。例えば、マクロを `#fourCharacterCode("AB" + "CD")` として呼び出そうとすると、コンパイラは「静的な文字列が必要です(Need a static string)」というエラーを表示します。
321321

322322
`expansion(of:in:)` メソッドは、AST で式を表す `SwiftSyntax` からの型である `ExprSyntax` のインスタンスを返します。この型は、`StringLiteralConvertible` プロトコルに準拠しているので、マクロの実装は、その結果を作成するために、軽量な構文として文字列リテラルを使用します。マクロの実装から返す `SwiftSyntax` の型はすべて、 `StringLiteralConvertible` に準拠しているので、あらゆる種類のマクロを実装するときにこのアプローチを使用することができます。
323323

language-reference/attributes.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 属性\(Attributes\)
22

3-
最終更新日: 2024/6/10
3+
最終更新日: 2025/2/22
44
原文: https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
55

66
宣言と型に情報を追加する。
@@ -93,7 +93,60 @@ _version number_ は、ピリオド\(`.`\)で区切られた 1〜3 個の正の
9393

9494
_version number_ は、ピリオド\(`.`\)で区切られた 1〜3 個の正の整数で構成されます。
9595

96-
* `message` 引数は、deprecated または obsoleted された宣言に使用した際に、コンパイラが表示する警告またはエラーのテキストメッセージを提供します。形式は次のとおりです:
96+
* `noasync` 引数は、宣言されたシンボルが非同期コンテキストで直接使用できないことを示します
97+
98+
Swift の並行処理では、潜在的な中断ポイント後に異なるスレッドで再開される可能性があるため、スレッドローカルストレージ、ロック、ミューテックス、セマフォなどを中断ポイントをまたいで使用すると、誤った結果につながる可能性があります。
99+
100+
この問題を回避するには、シンボルの宣言に `@available(*, noasync)` 属性を追加します:
101+
102+
```swift
103+
extension pthread_mutex_t {
104+
@available(*, noasync)
105+
mutating func lock() {
106+
pthread_mutex_lock(&self)
107+
}
108+
109+
@available(*, noasync)
110+
mutating func unlock() {
111+
pthread_mutex_unlock(&self)
112+
}
113+
}
114+
```
115+
116+
この属性は、誰かが非同期コンテキストでそのシンボルを使用しようとした場合にコンパイルエラーを発生させます。また、`message` 引数を使用してシンボルに関する追加情報も提供できます。
117+
118+
```swift
119+
@available(*, noasync, message: "Migrate locks to Swift concurrency.")
120+
mutating func lock() {
121+
pthread_mutex_lock(&self)
122+
}
123+
```
124+
125+
潜在的に安全でないシンボルを安全に使用できると保証できるのであれば、同期関数でラップし、その関数を非同期コンテキストから呼び出せます。
126+
127+
```swift
128+
// noasync 宣言を持つメソッドの同期ラッパを提供する
129+
extension pthread_mutex_t {
130+
mutating func withLock(_ operation: () -> ()) {
131+
self.lock()
132+
operation()
133+
self.unlock()
134+
}
135+
}
136+
137+
func downloadAndStore(key: Int,
138+
dataStore: MyKeyedStorage,
139+
dataLock: inout pthread_mutex_t) async {
140+
// 非同期コンテキストでラッパを安全に呼び出す
141+
dataLock.withLock {
142+
dataStore[key] = downloadContent()
143+
}
144+
}
145+
```
146+
147+
`noasync` 引数はほとんどの宣言で使用できますが、デイニシャライザの宣言では使用できません。Swift は同期・非同期の両方のコンテキストからクラスのデイニシャライザを呼び出せる必要があります。
148+
149+
* `message` 引数は、`deprecated``obsoleted``noasync` が付与された宣言に使用した際に、コンパイラが表示する警告またはエラーのテキストメッセージを提供します。形式は次のとおりです:
97150

98151
```swift
99152
message: <#message#>

language-reference/types.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# \(Types\)
22

3-
最終更新日: 2024/6/7
3+
最終更新日: 2025/2/22
44
原文: https://docs.swift.org/swift-book/ReferenceManual/Types.html
55

66
組み込みの名前付き型と複合型を使用します。
@@ -184,7 +184,7 @@ func takesTwoFunctions(first: (() -> Void) -> Void, second: (() -> Void) -> Void
184184

185185
上記のコードでは、`takesTwoFunctions(first:second:)` のパラメータは関数型です。どちらも `@esescaping` がマークされていないため、非エスケープです。
186186

187-
上記の例で「エラー」とマークされた 4 つの関数の呼び出しは、コンパイラエラーが発生します。最初と 2 番目のパラメータは非エスケープ関数のため、引数として別の非エスケープ関数をパラメータに渡すことはできません。対照的に、「OK」とマークされた 2 つの関数呼び出しは、コンパイラエラーが発生しません。これらの関数呼び出しは、`external``takesTwoFunctions(first:second:)` のパラメータではないため、制限に違反しません。
187+
上記の例で「エラー」とマークされた 4 つの関数の呼び出しは、コンパイルエラーが発生します。最初と 2 番目のパラメータは非エスケープ関数のため、引数として別の非エスケープ関数をパラメータに渡すことはできません。対照的に、「OK」とマークされた 2 つの関数呼び出しは、コンパイルエラーが発生しません。これらの関数呼び出しは、`external``takesTwoFunctions(first:second:)` のパラメータではないため、制限に違反しません。
188188

189189
この制限を回避する必要がある場合は、いずれかのパラメータを `@esescaping` とマークしたり、パラメータの非エスケープ関数の 1 つを `withoutActuallyEscaping(_:do:)` を使ってエスケープ関数に一時的に変換します。メモリへのアクセス競合を回避する方法については、[Memory Safety\(メモリ安全性\)](../language-guide/memory-safety.md)を参照ください。
190190

0 commit comments

Comments
 (0)