# 機能設計書 12-バックエンドタイムアウト取得

## 概要

本ドキュメントは、libuv の `uv_backend_timeout()` 関数によるI/Oポーリングのタイムアウト値取得機能について記述する。

### 本機能の処理概要

**業務上の目的・背景**：libuvのイベントループは、I/Oポーリング時に適切なタイムアウト値を使用してブロッキングする。タイマーハンドルの次回発火時刻やループの状態に基づき、ポーリングがどれだけの時間ブロックすべきかを決定する必要がある。外部イベントループにlibuvを組み込む際、この適切なタイムアウト値を取得するために本機能が使用される。

**機能の利用シーン**：`uv_backend_fd()` と組み合わせて、外部のイベントループ（GLib、Qt等）からlibuvのI/Oポーリングを駆動する場合に使用される。外部ループは `uv_backend_timeout()` の返り値をpoll/select等のタイムアウトとして利用する。また、libuv内部でも `uv_run()` のメインループ内でI/Oポーリングのタイムアウト値を決定するために使用される。

**主要な処理内容**：
1. ウォッチャーキューが空でない場合は即座に0を返す（I/Oポーリングの更新が必要）
2. ウォッチャーキューが空の場合、内部関数 `uv__backend_timeout()` に委譲する
3. 内部関数はループの停止フラグ、アクティブハンドル/リクエスト、保留キュー、アイドルハンドル、子プロセス回収フラグ、クローズ保留ハンドルの状態を確認
4. 全条件を満たす場合のみ、次のタイマー発火までの時間を返す

**関連システム・外部連携**：タイマーサブシステム（`uv__next_timeout()`）と連携して次回タイマー発火までの時間を取得する。

**権限による制御**：特になし。公開APIとして任意のスレッドから呼び出し可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | イベントループ | 主機能 | uv_backend_timeout()によるI/Oポーリングタイムアウト値取得のAPI定義 |

## 機能種別

データ取得（読み取り専用・計算処理あり）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | const uv_loop_t* | Yes | 対象のイベントループ | NULLチェックなし（呼び出し側の責任） |

### 入力データソース

呼び出し元から渡されるイベントループ構造体ポインタ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | I/Oポーリングのタイムアウト値（ミリ秒）。0はブロックしないことを意味し、-1は無期限ブロックを意味する |

### 出力先

関数の戻り値として呼び出し元へ返却。

## 処理フロー

### 処理シーケンス

```
1. uv_backend_timeout() が呼び出される
   └─ 引数として const uv_loop_t* loop を受け取る
2. ウォッチャーキューの空判定
   └─ 空でない場合: 0を返す（即座にuv_runを呼んでFD状態を更新する必要があるため）
3. 空の場合: uv__backend_timeout() を呼び出す
   └─ ループ状態のチェック:
      a. stop_flag が 0 でない → 0を返す
      b. アクティブハンドル/リクエストがない → 0を返す
      c. pending_queue が空でない → 0を返す
      d. idle_handles が空でない → 0を返す
      e. REAP_CHILDRENフラグがセット → 0を返す
      f. closing_handles がある → 0を返す
   └─ 全条件クリア: uv__next_timeout(loop) を返す
```

### フローチャート

```mermaid
flowchart TD
    A[uv_backend_timeout 呼び出し] --> B{watcher_queue が空?}
    B -->|No| C[0 を返却]
    B -->|Yes| D{stop_flag == 0?}
    D -->|No| C
    D -->|Yes| E{active handles/reqs あり?}
    E -->|No| C
    E -->|Yes| F{pending_queue 空?}
    F -->|No| C
    F -->|Yes| G{idle_handles 空?}
    G -->|No| C
    G -->|Yes| H{REAP_CHILDREN フラグなし?}
    H -->|No| C
    H -->|Yes| I{closing_handles なし?}
    I -->|No| C
    I -->|Yes| J[uv__next_timeout を返却]
    C --> K[終了]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 即時復帰条件 | ウォッチャーキューが空でない場合、0を返す | watcher_queueが空でない時 |
| BR-02 | 非ブロック条件 | pending/idle/closing等の処理待ちがある場合、0を返す | 各キューに要素がある時 |
| BR-03 | タイマー連動 | 全条件クリア時は次回タイマー発火時刻までのミリ秒を返す | ループがアクティブで処理待ちがない時 |

### 計算ロジック

`uv__next_timeout()` は、タイマーヒープの最小要素のタイムアウト値とループの現在時刻の差を計算して返す。タイマーがない場合は-1（無期限）を返す。

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

該当なし（インメモリのデータ構造操作のみ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | - | エラーを返さない | - |

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

O(1)の定数時間で完了。複数の条件判定とタイマーヒープの最小値参照のみ。

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

特になし。読み取り専用の操作。

## 備考

- `uv_backend_timeout()` の戻り値が0の場合、外部ループはlibuvのイベントループを即座に実行すべき
- 戻り値が-1の場合はタイマーが設定されていないため、I/Oイベントが発生するまで無期限にブロック可能
- libuv内部では `uv_run()` の中で `uv__backend_timeout()` が直接呼ばれる（L456）

---

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

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

### 推奨読解順序

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

イベントループ構造体の関連フィールドを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | L321: uv_backend_timeout() の関数宣言 |

**読解のコツ**: 戻り値の意味は、0=ブロックしない、正の値=ミリ秒タイムアウト、-1=無期限ブロックである。

#### Step 2: 公開API実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core.c (unix) | `src/unix/core.c` | L414-419: uv_backend_timeout() の Unix 実装。watcher_queue の空判定を行い、空なら uv__backend_timeout() に委譲する |

**主要処理フロー**:
1. **414行目**: `uv_backend_timeout()` 関数定義
2. **415行目**: `uv__queue_empty(&loop->watcher_queue)` で空判定
3. **416行目**: 空の場合 `uv__backend_timeout(loop)` を返す
4. **418行目**: 空でない場合 0 を返す

#### Step 3: 内部関数の判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | core.c (unix) | `src/unix/core.c` | L401-411: uv__backend_timeout() の実装。複数条件を確認して uv__next_timeout() を呼ぶか0を返す |

**主要処理フロー**:
- **402行目**: `loop->stop_flag == 0` の判定
- **404行目**: アクティブハンドル/リクエストの存在確認
- **405行目**: `pending_queue` の空判定
- **406行目**: `idle_handles` の空判定
- **407行目**: `UV_LOOP_REAP_CHILDREN` フラグの確認
- **408行目**: `closing_handles` の存在確認
- **409行目**: 全条件クリアで `uv__next_timeout(loop)` を返す

#### Step 4: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | core.c (win) | `src/win/core.c` | L414-424: Windows実装。Unix版と類似するが、Windows固有の条件（pending_reqs_tail等）を使用 |

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

```
uv_backend_timeout(loop)             [src/unix/core.c:414]
    │
    ├─ uv__queue_empty()             [queue.h - watcher_queue空判定]
    │
    └─ uv__backend_timeout(loop)     [src/unix/core.c:401]
           │
           ├─ uv__has_active_handles()  [src/uv-common.h - マクロ]
           ├─ uv__has_active_reqs()     [src/uv-common.h - マクロ]
           ├─ uv__queue_empty()         [queue.h - pending/idle判定]
           └─ uv__next_timeout(loop)    [src/timer.c]
```

### データフロー図

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

const uv_loop_t* loop ──> watcher_queue空判定 ──> [0 or 委譲]
                          │
                          └─> ループ状態チェック ──> [0]
                              │
                              └─> uv__next_timeout() ──> int (ms / -1)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | 公開API宣言（L321） |
| core.c (unix) | `src/unix/core.c` | ソース | Unix系実装（L401-419） |
| core.c (win) | `src/win/core.c` | ソース | Windows実装（L414-424） |
| timer.c | `src/timer.c` | ソース | uv__next_timeout() の実装 |
| uv-common.h | `src/uv-common.h` | ヘッダ | uv__has_active_handles/reqs マクロ定義 |
