# 機能設計書 30-タスク計算（task）

## 概要

本ドキュメントは、FSharp.Coreライブラリにおけるタスク計算（task）モジュールの設計を記述する。この機能は、F#のタスク計算式（task { ... }）を実現し、.NET TaskベースのAPIとの効率的な相互運用を提供する。

### 本機能の処理概要

F#のタスク計算式（task { ... }）を実装するためのライブラリ。.NETの`Task<'T>`を直接返すため、async/awaitベースのC#コードや.NET APIとの相互運用が容易。F#コンパイラのResumableStateMachine機能を活用し、同期的に完了するコードパスではアロケーションを最小化する。

**業務上の目的・背景**：.NETエコシステムではTaskベースの非同期APIが主流であり、F#からこれらのAPIを効率的に利用するための仕組みが必要。task計算式は、Asyncよりも低オーバーヘッドで.NET Taskと統合できる。

**機能の利用シーン**：.NET APIの非同期メソッド呼び出し、ASP.NET Coreコントローラー、高パフォーマンスが要求される非同期処理、C#との相互運用などで利用される。

**主要な処理内容**：
1. task計算式ビルダー: TaskBuilder（let!, do!, return!, return）
2. backgroundTask計算式: BackgroundTaskBuilder（UIスレッド考慮不要の場合）
3. バインド処理: Task<'T>、ValueTask<'T>、Async<'T>のバインド
4. 制御構造: try/with, try/finally, while, for
5. 状態マシン: ResumableStateMachineによる効率的な実装

**関連システム・外部連携**：.NET Task/TPL、ValueTask、Async<'T>。

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

## 関連画面

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

## 機能種別

非同期処理 / タスク / ユーティリティライブラリ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| task | Task<'T> | 関数依存 | 待機するタスク | - |
| valueTask | ValueTask<'T> | 関数依存 | 待機する値タスク | - |
| computation | Async<'T> | 関数依存 | 待機する非同期計算 | - |
| continuation | 'T -> TaskCode | 関数依存 | 継続処理 | - |

### 入力データソース

呼び出し元のF#コード、.NET API。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| タスク | Task<'T> | 計算結果を含むタスク |
| 結果値 | 'T | タスク完了時の結果 |

### 出力先

呼び出し元に返却。

## 処理フロー

### 処理シーケンス

```
1. task計算式の構築
   └─ TaskBuilderがlet!, do!, return等を変換
2. TaskStateMachineの初期化
   └─ ResumableStateMachineとTaskStateMachineDataを設定
3. Run関数で実行開始
   └─ AsyncTaskMethodBuilder.Startを呼び出し
4. MoveNextで状態遷移
   └─ 中断点でawaiterを設定、再開時に継続
5. 完了またはawait
   └─ SetResultまたはAwaitUnsafeOnCompleted
```

### フローチャート

```mermaid
flowchart TD
    A[開始: task計算式] --> B[TaskBuilder.Run]
    B --> C{__useResumableCode?}
    C -->|Yes| D[StateMachine方式]
    C -->|No| E[Dynamic方式]
    D --> F[MoveNextMethodImpl設定]
    E --> G[TaskResumptionDynamicInfo設定]
    F --> H[AsyncTaskMethodBuilder.Start]
    G --> H
    H --> I[MoveNext実行]
    I --> J{ステップ完了?}
    J -->|Yes| K[SetResult]
    J -->|No| L[AwaitUnsafeOnCompleted]
    L --> M[中断]
    M --> I
    K --> N[Task<'T>返却]
    N --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 状態マシン | ResumableStateMachineで効率的に実装 | すべての計算 |
| BR-02 | 同期パス最適化 | 同期完了時はアロケーション最小化 | IsCompleted=true |
| BR-03 | backgroundTask | SyncContextを考慮しない最適化 | backgroundTask使用時 |
| BR-04 | Async統合 | Async.StartImmediateAsTaskで変換 | Asyncバインド時 |

### 計算ロジック

```fsharp
// TaskStateMachineData構造体（28-35行目参照）
[<Struct; NoComparison; NoEquality>]
type TaskStateMachineData<'T> =
    [<DefaultValue(false)>]
    val mutable Result: 'T
    [<DefaultValue(false)>]
    val mutable MethodBuilder: AsyncTaskMethodBuilder<'T>

// TaskBuilder.Run（191-218行目参照）
member inline _.Run(code: TaskCode<'T, 'T>) : Task<'T> =
    if __useResumableCode then
        __stateMachine<TaskStateMachineData<'T>, Task<'T>>
            (MoveNextMethodImpl<_>(fun sm ->
                __resumeAt sm.ResumptionPoint
                let __stack_code_fin = code.Invoke(&sm)
                if __stack_code_fin then
                    sm.Data.MethodBuilder.SetResult(sm.Data.Result)))
            ...
    else
        TaskBuilder.RunDynamic(code)
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Exception | タスク内で例外発生 | SetExceptionで伝播 |
| - | AggregateException | 複数例外 | InnerExceptionsを確認 |
| - | TaskCanceledException | キャンセル時 | キャンセルトークンを確認 |

### リトライ仕様

アプリケーション層でリトライロジックを実装。

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

該当なし。

## パフォーマンス要件

- 同期完了パスでアロケーションフリー
- ResumableStateMachineによる効率的な状態遷移
- AsyncTaskMethodBuilderで.NETランタイムと統合
- backgroundTaskでSyncContextオーバーヘッド回避

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

- .NET Task同様のセキュリティモデル
- backgroundTaskはUIスレッドとの同期なし

## 備考

- task { ... } は Task<'T> を返す
- backgroundTask { ... } はSyncContextを無視
- F# 6.0で導入された機能
- C#のasync/awaitと同等のパフォーマンス

---

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

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

### 推奨読解順序

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

まず、タスク計算の基本的な型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskStateMachineData構造体（28-35行目） |
| 1-2 | tasks.fs | `src/FSharp.Core/tasks.fs` | 型エイリアス（36-39行目） |
| 1-3 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskCode型（39行目） |

**読解のコツ**: TaskStateMachineDataがResultとMethodBuilderを保持し、ResumableStateMachineと組み合わせて状態マシンを構成する。

#### Step 2: TaskBuilderBaseを理解する

基本的なビルダーメソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.Delay（43-44行目） |
| 2-2 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.Return（51-54行目） |
| 2-3 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.Combine（59-62行目） |
| 2-4 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.While（65-68行目） |
| 2-5 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.TryWith（72-75行目） |
| 2-6 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilderBase.TryFinally（79-87行目） |

**主要処理フロー**:
- **51-54行目**: Returnでsm.Data.Resultに結果を設定
- **59-62行目**: CombineはResumableCode.Combineに委譲
- **72-75行目**: TryWithはResumableCode.TryWithに委譲

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

タスクビルダーのRun実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilder.RunDynamic（153-189行目） |
| 3-2 | tasks.fs | `src/FSharp.Core/tasks.fs` | TaskBuilder.Run（191-218行目） |
| 3-3 | tasks.fs | `src/FSharp.Core/tasks.fs` | MoveNextMethodImpl（194-210行目） |

**主要処理フロー**:
- **153-189行目**: RunDynamicは動的実行方式
- **191-218行目**: Runは__useResumableCodeで分岐
- **202-203行目**: 完了時にSetResultを呼び出し

#### Step 4: BackgroundTaskBuilderを理解する

バックグラウンドタスクビルダーを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | tasks.fs | `src/FSharp.Core/tasks.fs` | BackgroundTaskBuilder.RunDynamic（224-233行目） |
| 4-2 | tasks.fs | `src/FSharp.Core/tasks.fs` | BackgroundTaskBuilder.Run（236-272行目） |
| 4-3 | tasks.fs | `src/FSharp.Core/tasks.fs` | SyncContext判定（227-229行目） |

**主要処理フロー**:
- **227-229行目**: SyncContextがnullかつTaskScheduler.Defaultの場合は直接実行
- **233行目**: そうでない場合はTask.Runで実行
- **266-270行目**: Run時も同様の判定を実行

#### Step 5: Bind拡張を理解する

様々な型のバインドサポートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | tasks.fs | `src/FSharp.Core/tasks.fs` | LowPriority.Bind（319-354行目） |
| 5-2 | tasks.fs | `src/FSharp.Core/tasks.fs` | HighPriority.Bind（435-462行目） |
| 5-3 | tasks.fs | `src/FSharp.Core/tasks.fs` | MediumPriority.Bind（502-505行目） |

**主要処理フロー**:
- **319-354行目**: 汎用的なGetAwaiterパターンをサポート
- **435-462行目**: Task<'T>専用の最適化されたバインド
- **502-505行目**: Async<'T>はStartImmediateAsTaskで変換

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

```
Task モジュール (tasks.fs)
    │
    ├─ 基本型
    │      ├─ TaskStateMachineData<'T>
    │      │      ├─ Result: 'T
    │      │      └─ MethodBuilder: AsyncTaskMethodBuilder<'T>
    │      ├─ TaskStateMachine<'T> = ResumableStateMachine<TaskStateMachineData<'T>>
    │      ├─ TaskResumptionFunc<'T>
    │      └─ TaskCode<'TOverall, 'T> = ResumableCode<...>
    │
    ├─ TaskBuilderBase
    │      ├─ Delay (遅延評価)
    │      ├─ Zero (空のコード)
    │      ├─ Return (結果設定)
    │      ├─ Combine (逐次実行)
    │      ├─ While (ループ)
    │      ├─ TryWith (例外処理)
    │      ├─ TryFinally (finally処理)
    │      └─ For (forループ)
    │
    ├─ TaskBuilder
    │      ├─ RunDynamic (動的実行)
    │      └─ Run (静的実行 / __useResumableCode)
    │             ├─ MoveNextMethodImpl
    │             ├─ SetStateMachineMethodImpl
    │             └─ AfterCode
    │
    ├─ BackgroundTaskBuilder
    │      ├─ RunDynamic (Task.Run使用)
    │      └─ Run (SyncContext判定)
    │
    └─ TaskBuilderExtensions
           ├─ LowPriority (汎用Bind)
           ├─ HighPriority (Task<'T>専用Bind)
           └─ MediumPriority (Async変換Bind)
```

### データフロー図

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

task { ... }
      │
      ▼
TaskBuilder
      │
      ├─ let! → Bind
      │     └─ awaiter.GetAwaiter()
      │     └─ IsCompleted判定
      │     └─ 完了 → continuation
      │     └─ 未完了 → AwaitUnsafeOnCompleted
      │
      ├─ return → Return
      │     └─ sm.Data.Result <- value
      │
      └─ Run
            │
            ▼
      __stateMachine or RunDynamic
            │
            ├─ MoveNext
            │     └─ __resumeAt sm.ResumptionPoint
            │     └─ code.Invoke(&sm)
            │     └─ SetResult or AwaitUnsafeOnCompleted
            │
            └─ AfterCode
                  └─ AsyncTaskMethodBuilder.Create()
                  └─ Start(&sm)
                  └─ sm.Data.MethodBuilder.Task
                        │
                        ▼
                   Task<'T>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tasks.fs | `src/FSharp.Core/tasks.fs` | ソース | TaskBuilder/BackgroundTaskBuilderの実装 |
| tasks.fsi | `src/FSharp.Core/tasks.fsi` | シグネチャ | 公開APIの定義 |
| resumable.fs | `src/FSharp.Core/resumable.fs` | ソース | ResumableStateMachine基盤 |
| async.fs | `src/FSharp.Core/async.fs` | ソース | Async統合 |
