# 通知設計書 7-ICriticalNotifyCompletion.UnsafeOnCompleted

## 概要

本ドキュメントは、.NET Runtimeにおける`ICriticalNotifyCompletion.UnsafeOnCompleted`メソッドの設計を記述する。このメソッドは、ExecutionContextを伝播せずに非同期操作完了時の継続処理をスケジュールするための高性能インターフェースメソッドである。

### 本通知の処理概要

`ICriticalNotifyCompletion.UnsafeOnCompleted`メソッドは、`INotifyCompletion`を継承したインターフェースの追加メソッドである。`OnCompleted`と異なり、ExecutionContextの伝播を行わないため、パフォーマンスが向上する。主にコンパイラ生成のasyncステートマシンで使用される。

**業務上の目的・背景**：`INotifyCompletion.OnCompleted`はExecutionContextをキャプチャして継続処理に伝播するため、セキュリティコンテキストや論理コールコンテキストが維持される。しかし、多くのシナリオではこの伝播が不要であり、オーバーヘッドとなる。`UnsafeOnCompleted`はこの伝播をスキップし、パフォーマンスを最適化する。C#コンパイラは通常、`ICriticalNotifyCompletion`が実装されている場合は`UnsafeOnCompleted`を優先的に使用する。

**通知の送信タイミング**：awaitされた操作が完了した時点で、登録された継続処理が実行される。`OnCompleted`と同様だが、ExecutionContextの伝播処理がスキップされる。

**通知の受信者**：登録された`Action`デリゲート（継続処理）が受信者となる。通常はコンパイラ生成のステートマシンのMoveNextメソッド。

**通知内容の概要**：継続処理自体には引数が渡されない。awaiterの`GetResult()`メソッドを呼び出すことで、非同期操作の結果を取得する。

**期待されるアクション**：継続処理（MoveNext）が実行され、ステートマシンが次の状態に遷移する。

## 通知種別

コールバック/継続通知（アプリ内通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（ExecutionContext伝播なし） |
| 優先度 | 高（非同期処理の継続に必須） |
| リトライ | なし |

### 送信先決定ロジック

`UnsafeOnCompleted`メソッドに渡された`Action`デリゲートが唯一の継続処理として登録される。

## 通知テンプレート

### インターフェース定義

```csharp
namespace System.Runtime.CompilerServices
{
    public interface ICriticalNotifyCompletion : INotifyCompletion
    {
        void UnsafeOnCompleted(Action continuation);
    }
}
```

### メソッドシグネチャ

| 項目 | 内容 |
|-----|------|
| メソッド名 | UnsafeOnCompleted |
| 引数 | `Action continuation` - 完了時に実行する継続処理 |
| 戻り値 | void |
| 例外 | `ArgumentNullException` - continuationがnullの場合 |

### OnCompletedとの違い

| 項目 | OnCompleted | UnsafeOnCompleted |
|-----|------------|-------------------|
| ExecutionContext伝播 | あり | なし |
| パフォーマンス | 標準 | 高速 |
| 用途 | 汎用 | パフォーマンス最適化 |
| コンパイラでの優先度 | 低 | 高 |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| continuation | 完了時に実行されるActionデリゲート | コンパイラ生成コード | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| プログラム実行 | 非同期操作の完了 | 操作が完了した場合 | Task完了、I/O完了など |
| プログラム実行 | 既に完了済み | IsCompletedがtrue | 同期的に継続を実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | 継続は常に1回だけ実行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[await式の評価] --> B[awaiter.IsCompleted確認]
    B -->|true| C[awaiter.GetResult呼び出し]
    B -->|false| D{ICriticalNotifyCompletion実装?}
    D -->|Yes| E[awaiter.UnsafeOnCompleted呼び出し]
    D -->|No| F[awaiter.OnCompleted呼び出し]
    E --> G[継続処理を登録<br/>ExecutionContext伝播なし]
    F --> H[継続処理を登録<br/>ExecutionContext伝播あり]
    G --> I[非同期操作の実行]
    H --> I
    I --> J{操作完了?}
    J -->|No| I
    J -->|Yes| K[継続処理を実行]
    K --> L[awaiter.GetResult呼び出し]
    C --> M[await式の評価完了]
    L --> M
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（メモリ内コールバック）

### 更新テーブル一覧

該当なし（メモリ内コールバック）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ArgumentNullException | continuationがnullの場合 | nullチェックを行う |
| 継続処理内例外 | 継続処理の実行中に例外が発生した場合 | 例外は呼び出し元に伝播 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（制限なし） |
| 1日あたり上限 | なし（制限なし） |

### 配信時間帯

制限なし

## セキュリティ考慮事項

- `UnsafeOnCompleted`はExecutionContextを伝播しないため、セキュリティコンテキストが維持されない
- "Unsafe"という名前が示す通り、セキュリティクリティカルなシナリオでは注意が必要
- 論理コールコンテキスト（AsyncLocal<T>等）の値も伝播されない
- 信頼されたコード内でのみ使用することを推奨

## 備考

- `System.Runtime.CompilerServices`名前空間に定義
- `ICriticalNotifyCompletion`は`INotifyCompletion`を継承
- C#コンパイラはasyncメソッドで`ICriticalNotifyCompletion`が利用可能な場合、`UnsafeOnCompleted`を優先使用
- `TaskAwaiter`、`ValueTaskAwaiter`、`ConfiguredTaskAwaiter`等がこのインターフェースを実装
- パフォーマンスクリティカルなシナリオでの使用を想定

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: インターフェース定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | INotifyCompletion.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs` | インターフェース定義（行24-34） |

**読解のコツ**: `ICriticalNotifyCompletion`が`INotifyCompletion`を継承していることを確認。XMLドキュメントコメントで「ExecutionContext情報を伝播しない」点を確認。

**主要処理フロー**:
1. **行24-26**: XMLドキュメント - await操作完了時の継続スケジュール
2. **行27**: `ICriticalNotifyCompletion : INotifyCompletion`の継承
3. **行29-32**: XMLドキュメント - OnCompletedと異なりExecutionContextを伝播しない
4. **行33**: `UnsafeOnCompleted`メソッドの定義

#### Step 2: TaskAwaiterでの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TaskAwaiter.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs` | UnsafeOnCompletedの実装（行56-59） |

**主要処理フロー**:
- **行20**: `TaskAwaiter : ICriticalNotifyCompletion`
- **行56-59**: `UnsafeOnCompleted`メソッド - `OnCompletedInternal`をflowExecutionContext=falseで呼び出し

#### Step 3: OnCompletedとの比較

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TaskAwaiter.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs` | OnCompletedとUnsafeOnCompletedの違い（行46-59） |

**主要処理フロー**:
- **行48**: `OnCompleted` - flowExecutionContext: true
- **行58**: `UnsafeOnCompleted` - flowExecutionContext: false

### プログラム呼び出し階層図

```
await someTask;
    │
    └─ コンパイラ生成コード
           │
           ├─ awaiter = someTask.GetAwaiter()
           │
           ├─ if (!awaiter.IsCompleted)
           │      │
           │      └─ awaiter.UnsafeOnCompleted(MoveNextAction)  // ICriticalNotifyCompletion実装の場合
           │             │
           │             └─ TaskAwaiter.OnCompletedInternal(task, continuation, true, false)
           │                    │                                                   ↑
           │                    │                               flowExecutionContext = false
           │                    ├─ ArgumentNullException.ThrowIfNull(continuation)
           │                    │
           │                    └─ task.SetContinuationForAwait(continuation, ...)
           │
           └─ result = awaiter.GetResult()
```

### データフロー図

```
[入力]                      [処理]                          [出力]

await式 ───▶ GetAwaiter() ───▶ IsCompleted確認
    │              │                  │
    │              ▼                  ▼
    │         TaskAwaiter       false: UnsafeOnCompleted()
    │              │                  │
    │              │                  ▼
    │              │     継続処理の登録（EC伝播なし）
    │              │                  │
    │              │                  ▼
    │              │         非同期操作の完了待ち
    │              │                  │
    ▼              ▼                  ▼
Action        タスク完了 ───▶ 継続処理の実行
(MoveNext)         │          （元のExecutionContext
                   │            は復元されない）
                   ▼
              GetResult() ───▶ 結果の取得
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| INotifyCompletion.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs` | ソース | インターフェース定義 |
| TaskAwaiter.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs` | ソース | Task用awaiter実装 |
| ValueTaskAwaiter.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs` | ソース | ValueTask用awaiter実装 |
| ConfiguredValueTaskAwaitable.cs | `src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs` | ソース | ConfigureAwait用awaiter |
