# 機能設計書 106-coro

## 概要

本ドキュメントは、Nim標準ライブラリの`coro`モジュールの機能設計を記述する。このモジュールは、協調的マルチタスキングを実現するコルーチン機能を提供する。

### 本機能の処理概要

`coro`モジュールは、複数のコルーチンを協調的に実行するためのスケジューラとコンテキスト切り替え機能を実装する。各プラットフォームに応じて、ucontext、setjmp/longjmp、Windowsファイバーなどのバックエンドを使用する。

**業務上の目的・背景**：非同期処理やイベント駆動プログラミングにおいて、複数の処理を軽量なスレッドのように並行実行したい場面がある。コルーチンは、OSスレッドよりも軽量でオーバーヘッドが少なく、明示的なyield/suspendによる協調的な切り替えを行うため、競合状態の管理が容易である。ゲームエンジン、ネットワークサーバー、シミュレーションなどで有用。

**機能の利用シーン**：協調的マルチタスキング、非同期I/Oシミュレーション、ゲームループでのタスク管理、状態マシンの実装など。

**主要な処理内容**：
1. コルーチンの作成とスケジュール（`start`）
2. コルーチンの一時停止と再開（`suspend`）
3. メインスケジューラループの実行（`run`）
4. コルーチン状態の確認（`alive`）
5. 他コルーチンの終了待機（`wait`）

**関連システム・外部連携**：OS固有のコンテキスト切り替えAPI（ucontext、Windows Fiber、setjmp/longjmp）。

**権限による制御**：権限による制御は存在しない。

## 関連画面

本モジュールは標準ライブラリであり、特定の画面との関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

並行処理 / コルーチン

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| c | proc() | Yes | コルーチンとして実行する関数 | クロージャ可 |
| stacksize | int | No | スタックサイズ（デフォルト512KB） | 正の整数 |
| sleepTime | float | No | 一時停止時間（秒） | 0以上 |
| interval | float | No | 待機時のポーリング間隔（秒） | 正の数 |

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CoroutineRef | ref object | コルーチンへの参照 |
| bool | bool | コルーチンの生存状態 |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. 初期化 (initialize)
   └─ CoroutineLoopContext作成
   └─ スケジューラ用メインコルーチン設定

2. コルーチン作成 (start)
   └─ Coroutineオブジェクト作成
   └─ スタック領域確保
   └─ コルーチンリストに追加

3. スケジューラ実行 (run)
   └─ リスト内のコルーチンを順に実行
   └─ sleepTime経過後に再開
   └─ 終了したコルーチンを削除

4. 一時停止 (suspend)
   └─ 現在のコルーチンを中断
   └─ メインループにコンテキスト切り替え
```

### フローチャート

```mermaid
flowchart TD
    A[開始: start] --> B[Coroutineオブジェクト作成]
    B --> C[スタック領域確保]
    C --> D[コルーチンリストに追加]
    D --> E[CoroutineRef返却]

    F[開始: run] --> G[initialize]
    G --> H[current = head]
    H --> I{currentがnil?}
    I -->|Yes| J[終了]
    I -->|No| K{sleepTime経過?}
    K -->|Yes| L[switchTo実行]
    K -->|No| M[次のコルーチンへ]
    L --> N{状態がFINISHED?}
    N -->|Yes| O[コルーチン削除]
    N -->|No| M
    O --> M
    M --> I

    P[開始: suspend] --> Q[sleepTime設定]
    Q --> R[メインループへswitchTo]
    R --> S[再開時にここから継続]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 協調的切り替え | コルーチンはsuspend呼び出しでのみ切り替わる | 常時 |
| BR-02 | デフォルトスタック | スタックサイズのデフォルトは512KB | start呼び出し時 |
| BR-03 | コンパイルフラグ | `-d:nimCoroutines`が必要 | コンパイル時 |
| BR-04 | バックエンド選択 | プラットフォームに応じて自動選択 | コンパイル時 |

### 計算ロジック

**コルーチン状態**:
- `CORO_CREATED (0)`: 作成済み、未開始
- `CORO_EXECUTING (1)`: 実行中
- `CORO_FINISHED (2)`: 終了

**バックエンド選択ロジック**:
```nim
when defined(windows):
  const coroBackend = CORO_BACKEND_FIBERS
elif defined(haiku) or defined(openbsd):
  const coroBackend = CORO_BACKEND_SETJMP
elif defined(nimCoroutinesSetjmp):
  const coroBackend = CORO_BACKEND_SETJMP
else:
  const coroBackend = CORO_BACKEND_UCONTEXT
```

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| コンパイルエラー | ビルドエラー | `-d:nimCoroutines`なし | フラグを追加 |
| 未キャッチ例外 | 実行時 | コルーチン内で例外発生 | try-exceptで捕捉 |

### リトライ仕様

リトライは不要。例外発生時はコルーチンがFINISHED状態になる。

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

トランザクション管理は不要。

## パフォーマンス要件

- コンテキスト切り替え: 数マイクロ秒
- スタックメモリ: コルーチンあたり512KB（設定可能）
- スケジューリングオーバーヘッド: 最小限

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

- スタックオーバーフローの可能性
- GCとの連携のため、適切なスタックボトム設定が必要

## 備考

- APIは「Unstable」としてマーク
- ARC/ORC GCでは一部の処理がスキップされる
- arm64での動作に問題がある可能性（bug #17178）

---

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

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

### 推奨読解順序

#### Step 1: 条件コンパイルとバックエンド選択を理解する

プラットフォーム別のバックエンド選択ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | coro.nim | `lib/pure/coro.nim` | 26-30行目: `-d:nimCoroutines`必須チェック |
| 1-2 | coro.nim | `lib/pure/coro.nim` | 49-67行目: バックエンド定数と選択ロジック |
| 1-3 | coro.nim | `lib/pure/coro.nim` | 69-132行目: バックエンド別の型定義とimport |

**読解のコツ**: `CORO_BACKEND_UCONTEXT`, `CORO_BACKEND_SETJMP`, `CORO_BACKEND_FIBERS`の3つのバックエンドがあり、whenで切り替わる。

#### Step 2: データ構造を理解する

Coroutine型とコンテキスト構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | coro.nim | `lib/pure/coro.nim` | 144-148行目: コルーチン状態定数 |
| 2-2 | coro.nim | `lib/pure/coro.nim` | 150-162行目: Stack, Coroutine型定義 |
| 2-3 | coro.nim | `lib/pure/coro.nim` | 164-178行目: CoroutineRef, CoroutineLoopContext |
| 2-4 | coro.nim | `lib/pure/coro.nim` | 180行目: スレッドローカルなctx変数 |

**主要処理フロー**:
- **155行目**: Coroutineにはコンテキスト、関数ポインタ、状態、スタック等を格納
- **174-178行目**: CoroutineLoopContextはコルーチンリストとメインループを保持

#### Step 3: コンテキスト切り替えを理解する

switchTo関数の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | coro.nim | `lib/pure/coro.nim` | 203-233行目: switchTo関数 |

**主要処理フロー**:
- **205行目**: lastRunを更新
- **207-209行目**: GCスタック設定
- **213-228行目**: バックエンド別のコンテキスト切り替え

#### Step 4: 公開APIを理解する

start、suspend、run関数を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | coro.nim | `lib/pure/coro.nim` | 235-241行目: suspend関数 |
| 4-2 | coro.nim | `lib/pure/coro.nim` | 270-296行目: start関数 |
| 4-3 | coro.nim | `lib/pure/coro.nim` | 298-337行目: run関数 |
| 4-4 | coro.nim | `lib/pure/coro.nim` | 339-345行目: alive, wait関数 |

**主要処理フロー**:
- **270-296行目**: startでCoroutineオブジェクト作成、スタック確保
- **298-337行目**: runでスケジューラループ、各コルーチンを順に実行
- **235-241行目**: suspendでメインループへ戻る

#### Step 5: コルーチン実行処理を理解する

runCurrentTask関数を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | coro.nim | `lib/pure/coro.nim` | 243-268行目: runCurrentTask関数 |

**主要処理フロー**:
- **249行目**: スタックボトムを設定
- **259行目**: 状態をEXECUTINGに変更
- **261行目**: コルーチン関数を実行
- **265行目**: 終了後に状態をFINISHEDに変更

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

```
coro.nim
    │
    ├─ バックエンド
    │      ├─ FIBERS (Windows)
    │      │      └─ CreateFiberEx, SwitchToFiber, DeleteFiber
    │      ├─ UCONTEXT (Unix)
    │      │      └─ getcontext, setcontext, swapcontext, makecontext
    │      └─ SETJMP (Unix x86/64)
    │             └─ setjmp, longjmp, coroExecWithStack
    │
    ├─ データ構造
    │      ├─ Coroutine {execContext, fn, state, stack, ...}
    │      ├─ CoroutineRef {coro: CoroutinePtr}
    │      └─ CoroutineLoopContext {coroutines, current, loop}
    │
    ├─ 内部関数
    │      ├─ initialize ─── CoroutineLoopContext初期化
    │      ├─ getCurrent ─── 現在のコルーチン取得
    │      ├─ switchTo ─── コンテキスト切り替え
    │      └─ runCurrentTask ─── コルーチン関数実行
    │
    └─ 公開API
           ├─ start ─── Coroutine作成、リストに追加
           ├─ suspend ─── 一時停止、メインループへ切り替え
           ├─ run ─── スケジューラループ
           ├─ alive ─── 生存確認
           └─ wait ─── 終了待機
```

### データフロー図

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

proc() ─────────────────▶ start ───────────────────▶ CoroutineRef
                              │
                              ├─ Coroutine作成
                              ├─ スタック確保
                              └─ リストに追加

(スケジューラ開始) ─────▶ run ─────────────────────▶ (全コルーチン完了)
                              │
                              └─▶ switchTo ──▶ runCurrentTask
                                     │              │
                                     │              └─▶ fn() 実行
                                     │              │
                                     │◀─────────────┘ suspend

(コルーチン内) ──────────▶ suspend ─────────────────▶ (一時停止)
                              │
                              └─▶ switchTo(メインループへ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| coro.nim | `lib/pure/coro.nim` | ソース | メインモジュール、全機能の実装 |
| coro_detection.nim | `system/coro_detection.nim` | 依存 | コルーチンフラグ検出 |
| lists.nim | `lib/pure/lists.nim` | 依存 | DoublyLinkedList |
| os.nim | `lib/pure/os.nim` | 依存 | sleep関数 |
| timers.nim | `system/timers.nim` | 依存 | getTicks関数 |
| amd64.S | `lib/arch/x86/amd64.S` | 依存 | setjmpバックエンド用アセンブリ（64bit） |
| i386.S | `lib/arch/x86/i386.S` | 依存 | setjmpバックエンド用アセンブリ（32bit） |
