# 機能設計書 29-非同期計算（Async）

## 概要

本ドキュメントは、FSharp.Coreライブラリにおける非同期計算モジュール（Async）の設計を記述する。この機能は、F#の非同期プログラミングモデルを実現するコア機能を提供する。

### 本機能の処理概要

F#の非同期計算（async workflow）を実現するためのライブラリ。async計算式（async { ... }）の基盤となる型と関数を提供し、非同期処理の合成、キャンセル、例外処理を統一的に扱うことができる。継続渡しスタイル（CPS）をベースとした実装で、トランポリンを使用してスタックオーバーフローを防止する。

**業務上の目的・背景**：非同期I/O、並行処理、バックグラウンド処理などを効率的に記述するためのプログラミングモデル。.NETのTask/async-awaitとは異なるF#独自のモデルを提供し、キャンセルトークンの自動伝播や例外処理の統一的な扱いを実現する。

**機能の利用シーン**：非同期I/O操作（ファイル、ネットワーク）、並行計算、バックグラウンドタスク、タイムアウト処理、キャンセル可能な操作の実装などで利用される。

**主要な処理内容**：
1. async計算式ビルダー: AsyncBuilder（let!, do!, return!, return）
2. 実行関数: Async.RunSynchronously, Async.Start, Async.StartAsTask
3. 合成関数: Async.Parallel, Async.Sequential, Async.Choice
4. 制御関数: Async.Sleep, Async.AwaitTask, Async.FromContinuations
5. キャンセル処理: CancellationToken, Async.CancellationToken
6. 例外処理: try/with, try/finally

**関連システム・外部連携**：.NET Task/TPL、CancellationToken、SynchronizationContext。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | ライブラリ機能のためUI関連なし |

## 機能種別

非同期処理 / 並行処理 / ユーティリティライブラリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| computation | Async<'T> | Yes | 非同期計算 | - |
| cancellationToken | CancellationToken | No | キャンセルトークン | - |
| timeout | int | No | タイムアウト（ミリ秒） | 正の整数 |
| continuation | 'T -> unit | 関数依存 | 成功時の継続 | - |
| exceptionContinuation | exn -> unit | 関数依存 | 例外時の継続 | - |
| cancellationContinuation | OperationCanceledException -> unit | 関数依存 | キャンセル時の継続 | - |

### 入力データソース

呼び出し元のF#コード。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 非同期計算 | Async<'T> | 合成された非同期計算 |
| 結果値 | 'T | 同期実行時の結果 |
| タスク | Task<'T> | .NET Taskに変換した結果 |
| unit | unit | 副作用のみの処理の結果 |

### 出力先

呼び出し元に返却、または継続関数に渡される。

## 処理フロー

### 処理シーケンス

```
1. Async計算式の構築
   └─ AsyncBuilderがlet!, do!, return等を変換
2. 継続の連鎖を構築
   └─ cont（成功）、econt（例外）、ccont（キャンセル）
3. AsyncActivationで実行コンテキストを作成
   └─ キャンセルトークン、トランポリンを設定
4. 計算を開始
   └─ Invoke関数で継続を呼び出し
5. トランポリンでスタックを管理
   └─ 一定回数のBindでスタックをリセット
```

### フローチャート

```mermaid
flowchart TD
    A[開始: Async計算式] --> B[AsyncBuilderでAsyncを構築]
    B --> C{実行方法}
    C -->|RunSynchronously| D[同期的に実行]
    C -->|Start| E[バックグラウンドで実行]
    C -->|StartAsTask| F[Taskとして実行]
    D --> G[AsyncActivation作成]
    E --> G
    F --> G
    G --> H[cont/econt/ccont設定]
    H --> I[Invokeで計算開始]
    I --> J{結果}
    J -->|成功| K[contを呼び出し]
    J -->|例外| L[econtを呼び出し]
    J -->|キャンセル| M[ccontを呼び出し]
    K --> N[終了]
    L --> N
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 継続渡しスタイル | Asyncはcont, econt, ccontの3継続で実装 | すべての計算 |
| BR-02 | トランポリン | 300回のBindごとにスタックをリセット | 深い再帰 |
| BR-03 | キャンセル伝播 | キャンセルトークンは自動的に伝播 | すべての計算 |
| BR-04 | SyncContext復帰 | UIスレッドなどへの復帰をサポート | Start系関数 |

### 計算ロジック

```fsharp
// Async<'T>の構造（79行目参照）
type cont<'T> = 'T -> AsyncReturn
type econt = ExceptionDispatchInfo -> AsyncReturn
type ccont = OperationCanceledException -> AsyncReturn

// Async<'T>型（427-430行目参照）
type Async<'T> =
    {
        Invoke: AsyncActivation<'T> -> AsyncReturn
    }

// Bindの実装（581-588行目参照）
let Bind (ctxt: AsyncActivation<'T>) (part1: Async<'U>) (part2: 'U -> Async<'T>) : AsyncReturn =
    if ctxt.IsCancellationRequested then
        ctxt.OnCancellation()
    else
        Invoke part1 (ctxt.WithContinuation(fun result1 -> CallThenInvokeNoHijackCheck ctxt result1 part2))
```

## データベース操作仕様

### 操作別データベース影響一覧

該当なし。純粋なインメモリ操作。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | OperationCanceledException | キャンセルが要求された場合 | キャンセル継続で処理 |
| - | TimeoutException | タイムアウトした場合 | タイムアウト値を調整 |
| - | AggregateException | Parallel実行で複数例外 | InnerExceptionsを確認 |
| - | Exception | 任意の例外 | 例外継続で処理 |

### リトライ仕様

アプリケーション層でリトライロジックを実装。Async自体はリトライ機能を提供しない。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- トランポリンで300回ごとにスタックリセット（bindLimitBeforeHijack定数、87行目）
- 継続渡しスタイルによる効率的なメモリ使用
- SuspendedAsyncでSyncContextへの効率的な復帰
- ResultCellでスレッド間の結果同期

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

- キャンセルトークンの適切な伝播
- 例外情報のExceptionDispatchInfoでの保持
- スレッドプール使用時のセキュリティコンテキスト

## 備考

- Async<'T>は.NETのTaskと相互変換可能
- async計算式はAsyncBuilderで実装
- トランポリンパターンでスタックオーバーフローを防止
- LinkedSubSourceでキャンセルトークンの連結をサポート

---

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

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

### 推奨読解順序

#### Step 1: 基本型を理解する

まず、非同期計算の基本的な型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | async.fs | `src/FSharp.Core/async.fs` | cont, econt, ccont型（79-81行目） |
| 1-2 | async.fs | `src/FSharp.Core/async.fs` | AsyncReturn型（72-78行目） |
| 1-3 | async.fs | `src/FSharp.Core/async.fs` | Async<'T>型（427-430行目） |
| 1-4 | async.fs | `src/FSharp.Core/async.fs` | AsyncResult<'T>型（443-454行目） |

**読解のコツ**: 継続渡しスタイル（CPS）を理解することが鍵。cont（成功）、econt（例外）、ccont（キャンセル）の3つの継続が非同期計算の基盤。

#### Step 2: トランポリンを理解する

スタックオーバーフロー防止のトランポリン機構を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | async.fs | `src/FSharp.Core/async.fs` | Trampolineクラス（84-167行目） |
| 2-2 | async.fs | `src/FSharp.Core/async.fs` | bindLimitBeforeHijack（87行目） |
| 2-3 | async.fs | `src/FSharp.Core/async.fs` | TrampolineHolderクラス（168-253行目） |

**主要処理フロー**:
- **87行目**: 300回のBindでスタックをリセット
- **101-148行目**: Execute関数でトランポリンループを実行
- **152-154行目**: IncrementBindCountでカウント管理

#### Step 3: AsyncActivationを理解する

非同期計算の実行コンテキストを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | async.fs | `src/FSharp.Core/async.fs` | AsyncActivationAux（257-270行目） |
| 3-2 | async.fs | `src/FSharp.Core/async.fs` | AsyncActivationContents（275-282行目） |
| 3-3 | async.fs | `src/FSharp.Core/async.fs` | AsyncActivation構造体（287-423行目） |

**主要処理フロー**:
- **340行目**: tokenプロパティでキャンセルトークンを提供
- **365-369行目**: Success静的メソッドで成功継続を呼び出し
- **381-392行目**: Create静的メソッドで初期化

#### Step 4: プリミティブ関数を理解する

AsyncPrimitivesモジュールの基本関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | async.fs | `src/FSharp.Core/async.fs` | MakeAsync（561-562行目） |
| 4-2 | async.fs | `src/FSharp.Core/async.fs` | Invoke（472-473行目） |
| 4-3 | async.fs | `src/FSharp.Core/async.fs` | Bind（581-588行目） |
| 4-4 | async.fs | `src/FSharp.Core/async.fs` | TryFinally（596-623行目） |
| 4-5 | async.fs | `src/FSharp.Core/async.fs` | TryWith（633-644行目） |

**主要処理フロー**:
- **561-562行目**: MakeAsyncでAsync<'T>を構築
- **581-588行目**: Bindで継続を連鎖
- **596-623行目**: TryFinallyで例外/キャンセル時もfinally実行

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

```
Async モジュール (async.fs)
    │
    ├─ 基本型
    │      ├─ cont<'T> = 'T -> AsyncReturn
    │      ├─ econt = ExceptionDispatchInfo -> AsyncReturn
    │      ├─ ccont = OperationCanceledException -> AsyncReturn
    │      └─ Async<'T> = { Invoke: AsyncActivation<'T> -> AsyncReturn }
    │
    ├─ スタック管理
    │      ├─ Trampoline
    │      │      ├─ Execute (トランポリンループ)
    │      │      ├─ IncrementBindCount
    │      │      └─ Set (継続を保存)
    │      └─ TrampolineHolder
    │             ├─ ExecuteWithTrampoline
    │             ├─ PostWithTrampoline
    │             └─ QueueWorkItemWithTrampoline
    │
    ├─ 実行コンテキスト
    │      ├─ AsyncActivationAux (token, econt, ccont, trampolineHolder)
    │      └─ AsyncActivation<'T>
    │             ├─ WithContinuation
    │             ├─ WithExceptionContinuation
    │             ├─ Success (成功継続呼び出し)
    │             └─ OnCancellation
    │
    ├─ AsyncPrimitives
    │      ├─ MakeAsync / MakeAsyncWithCancelCheck
    │      ├─ Invoke (計算実行)
    │      ├─ Bind (継続連鎖)
    │      ├─ TryFinally / TryWith
    │      ├─ CreateReturnAsync / CreateBindAsync
    │      ├─ CreateWhileAsync / CreateForLoopAsync
    │      └─ CreateSwitchToAsync / CreateSwitchToThreadPoolAsync
    │
    └─ ユーティリティ
           ├─ LinkedSubSource (キャンセルトークン連結)
           ├─ Latch (一度だけ実行)
           ├─ AsyncResult<'T> (Ok | Error | Canceled)
           ├─ SuspendedAsync (SyncContext復帰)
           └─ ResultCell (スレッド間結果同期)
```

### データフロー図

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

async { ... }
      │
      ▼
AsyncBuilder
      │
      ├─ let! → Bind
      ├─ do!  → Bind >> ignore
      ├─ return → Return
      └─ return! → ReturnFrom
      │
      ▼
Async<'T> ───▶ AsyncActivation作成 ───▶ 結果
                      │
                      ├─ cont (成功継続)
                      ├─ econt (例外継続)
                      ├─ ccont (キャンセル継続)
                      └─ trampolineHolder
                      │
                      ▼
                  Invoke実行
                      │
                      ├─ 成功 → cont呼び出し → 結果値
                      ├─ 例外 → econt呼び出し → 例外処理
                      └─ キャンセル → ccont呼び出し → キャンセル処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| async.fs | `src/FSharp.Core/async.fs` | ソース | Asyncモジュールのメイン実装 |
| async.fsi | `src/FSharp.Core/async.fsi` | シグネチャ | 公開APIの定義 |
| control.fs | `src/FSharp.Core/control.fs` | ソース | AsyncBuilder実装 |
| control.fsi | `src/FSharp.Core/control.fsi` | シグネチャ | 公開APIの定義 |
| tasks.fs | `src/FSharp.Core/tasks.fs` | ソース | Task統合 |
