# 機能設計書 1-イベントループ初期化

## 概要

本ドキュメントは、libuvライブラリにおけるイベントループ初期化機能（`uv_loop_init()`）の設計仕様を記述する。イベントループはlibuvの中核となるデータ構造であり、すべての非同期I/O操作の基盤となる。

### 本機能の処理概要

`uv_loop_init()`は、`uv_loop_t`構造体を初期化し、イベントループとして使用可能な状態にする関数である。内部データ構造の初期化、プラットフォーム固有のバックエンドの初期化、シグナル処理の準備、スレッドプール連携用の非同期ハンドルの初期化など、多岐にわたる初期化処理を行う。

**業務上の目的・背景**：libuvを使用した非同期I/Oプログラムの最初のステップとして、イベントループの初期化が必要である。イベントループは、タイマー、ネットワークI/O、ファイルシステム操作、シグナル処理など、すべての非同期処理を管理する中心的なデータ構造であり、正しく初期化されなければライブラリの他のいかなる機能も使用できない。

**機能の利用シーン**：アプリケーション起動時にカスタムイベントループを作成する場合や、スレッドごとに独立したイベントループが必要な場合に使用される。デフォルトループ（`uv_default_loop()`）を使用する場合は内部的に呼び出されるため、明示的な呼び出しは不要である。

**主要な処理内容**：
1. `uv_loop_t`構造体のゼロクリア（ユーザーデータ`data`フィールドは保持）
2. 内部フィールド（`uv__loop_internal_fields_t`）のメモリ確保と初期化
3. メトリクス用ミューテックスの初期化
4. タイマーヒープ、各種キュー（ワークキュー、アイドル、非同期、チェック、準備、ハンドルキュー等）の初期化
5. I/Oウォッチャー関連フィールドの初期化
6. 内部時刻キャッシュの更新
7. プラットフォーム固有のI/Oバックエンド（kqueue/epoll/iocp等）の初期化
8. シグナル処理サブシステムの初期化
9. プロセス管理サブシステムの初期化
10. cloexecロックとワークキューミューテックスの初期化
11. スレッドプール連携用非同期ハンドル（`wq_async`）の初期化

**関連システム・外部連携**：プラットフォーム固有のI/Oイベント通知機構（macOS: kqueue、Linux: epoll、Windows: IOCP）と連携する。

**権限による制御**：特に権限制御はない。ただし、プラットフォーム固有のリソース（ファイルディスクリプタ等）の確保に失敗する場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | APIドキュメント一覧 | 遷移先機能 | 各APIリファレンスページへのリンク一覧（イベントループ） |
| 6 | イベントループ | 主機能 | uv_loop_init()によるイベントループ初期化のAPI定義と使用例 |
| 33 | 基本事項 | 主機能 | uv_loop_init()を使ったイベントループの基本的な使い方の解説 |
| 38 | イベントループ応用 | 主機能 | 複数イベントループの管理方法・他ライブラリへの組み込みの解説 |
| 42 | 0.10→1.0.0マイグレーション | 補助機能 | uv_loop_init()へのAPI変更（0.10→1.0.0）の説明 |

## 機能種別

初期化処理 / リソース確保

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | 初期化対象のイベントループ構造体へのポインタ | NULLの場合は未定義動作（バリデーションなし） |

### 入力データソース

呼び出し元が事前にメモリ確保した`uv_loop_t`構造体。スタック上またはヒープ上に確保されたものを受け取る。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、失敗時は負のエラーコード（UV_ENOMEM等） |
| loop（初期化済み） | uv_loop_t* | 初期化された全フィールドを持つイベントループ構造体 |

### 出力先

入力として受け取った`uv_loop_t`構造体がin-placeで初期化される。

## 処理フロー

### 処理シーケンス

```
1. ユーザーデータ(data)の退避
   └─ loop->dataを一時変数に保存
2. 構造体のゼロクリア
   └─ memset(loop, 0, sizeof(*loop))でクリア後、dataを復元
3. 内部フィールドのメモリ確保
   └─ uv__calloc()でuv__loop_internal_fields_tを確保（失敗時UV_ENOMEM）
4. メトリクス用ミューテックスの初期化
   └─ uv_mutex_init(&lfields->loop_metrics.lock)
5. 各種キュー・ヒープの初期化
   └─ timer_heap, wq, idle_handles, async_handles, check_handles, prepare_handles, handle_queue, pending_queue, watcher_queue
6. カウンタ・ウォッチャーの初期設定
   └─ active_handles=0, active_reqs.count=0, nfds=0, nwatchers=0
7. 内部時刻キャッシュの更新
   └─ uv__update_time(loop)
8. ファイルディスクリプタの初期値設定
   └─ async_io_watcher.fd=-1, async_wfd=-1, signal_pipefd=-1, backend_fd=-1, emfile_fd=-1
9. プラットフォーム固有バックエンドの初期化
   └─ uv__platform_loop_init(loop)（kqueue/epollの初期化）
10. シグナル処理の初期化
    └─ uv__signal_global_once_init() + uv__process_init(loop)
11. cloexecロックの初期化
    └─ uv_rwlock_init(&loop->cloexec_lock)
12. ワークキューミューテックスの初期化
    └─ uv_mutex_init(&loop->wq_mutex)
13. スレッドプール連携用非同期ハンドルの初期化
    └─ uv_async_init(loop, &loop->wq_async, uv__work_done)
14. 内部ハンドルの参照カウント解除
    └─ uv__handle_unref(&loop->wq_async) + UV_HANDLE_INTERNALフラグ設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[loop->data退避 + memsetクリア + data復元]
    B --> C[内部フィールドメモリ確保]
    C --> D{確保成功?}
    D -->|No| E[UV_ENOMEM返却]
    D -->|Yes| F[メトリクスmutex初期化]
    F --> G{mutex初期化成功?}
    G -->|No| H[メモリ解放 + エラー返却]
    G -->|Yes| I[各種キュー・ヒープ初期化]
    I --> J[プラットフォームバックエンド初期化]
    J --> K{成功?}
    K -->|No| L[クリーンアップ + エラー返却]
    K -->|Yes| M[シグナル・プロセス初期化]
    M --> N[cloexecロック・wq mutex初期化]
    N --> O[wq_async非同期ハンドル初期化]
    O --> P{全て成功?}
    P -->|No| Q[段階的クリーンアップ + エラー返却]
    P -->|Yes| R[wq_asyncの参照解除 + INTERNALフラグ設定]
    R --> S[0を返却して終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ユーザーデータ保持 | loop->dataフィールドはゼロクリア時に退避・復元され、初期化前の値が保持される | 常時 |
| BR-02 | 段階的クリーンアップ | 初期化途中でエラーが発生した場合、既に確保したリソースを逆順に解放する | エラー発生時 |
| BR-03 | 内部ハンドル参照制御 | wq_asyncは内部ハンドルとして扱い、ループ生存判定に影響しないよう参照カウントを解除する | 常時 |

### 計算ロジック

特になし。

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

該当なし（libuvはデータベースを使用しない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_ENOMEM | メモリ不足 | 内部フィールド用メモリ確保に失敗 | メモリを解放してリトライ、またはプロセス終了 |
| プラットフォーム固有エラー | システムエラー | kqueue/epollのファイルディスクリプタ作成失敗 | ファイルディスクリプタリミット拡張を検討 |
| UV_ENOMEM | メモリ不足 | ミューテックス初期化失敗 | メモリ解放後にリトライ |

### リトライ仕様

初期化失敗時のリトライ機構は組み込まれていない。呼び出し元でリソースを解放してから再試行する必要がある。

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

該当なし。初期化処理はアトミックではなく、途中失敗時はgotoベースの段階的クリーンアップ（fail_async_init → fail_mutex_init → fail_rwlock_init → fail_process_init → fail_platform_init → fail_metrics_mutex_init）で対処する。

## パフォーマンス要件

初期化は一度だけ実行される処理であり、パフォーマンス要件は特にない。ただし、プラットフォーム固有のバックエンド初期化でシステムコール（`kqueue()`、`epoll_create1()`等）が発行される。

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

- `memset`によるゼロクリアで、前回使用時のデータが残留しないようにしている
- cloexecロックにより、マルチスレッド環境でのファイルディスクリプタのclose-on-exec設定競合を防止

## 備考

- `uv_loop_new()`は非推奨（DEPRECATED）であり、代わりにユーザーがメモリを確保して`uv_loop_init()`を使用することが推奨される
- `uv_loop_init()`で初期化したループは、使用後に必ず`uv_loop_close()`で終了処理を行う必要がある

---

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

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

### 推奨読解順序

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

まず、イベントループ構造体`uv_loop_t`の定義と、内部フィールドの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **1941-1956行目**: `uv_loop_s`構造体の定義。data, active_handles, handle_queue, active_reqs, internal_fields, stop_flag、およびUV_LOOP_PRIVATE_FIELDSマクロによるプラットフォーム固有フィールド |
| 1-2 | uv.h | `include/uv.h` | **261-266行目**: `uv_loop_option`列挙型。UV_LOOP_BLOCK_SIGNAL, UV_METRICS_IDLE_TIME, UV_LOOP_USE_IO_URING_SQPOLL |
| 1-3 | unix.h | `include/uv/unix.h` | UV_LOOP_PRIVATE_FIELDSマクロの定義。timer_heap, pending_queue, watcher_queue, watchers, nwatchers, nfds, backend_fd, closing_handles等のUnix固有フィールド |

**読解のコツ**: `uv_loop_s`構造体はpublicフィールドとprivateフィールド（`UV_LOOP_PRIVATE_FIELDS`マクロ）に分かれている。privateフィールドはプラットフォームごとに異なるため、`include/uv/unix.h`または`include/uv/win.h`を参照する必要がある。

#### Step 2: エントリーポイントを理解する

`uv_loop_init()`の実装本体がどこにあるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | **291行目**: `uv_loop_init()`のAPI宣言 |
| 2-2 | loop.c | `src/unix/loop.c` | **30-132行目**: `uv_loop_init()`の実装本体 |

**主要処理フロー**:
1. **35-37行目**: `loop->data`の退避とmemsetによるゼロクリア、dataの復元
2. **39-42行目**: `uv__loop_internal_fields_t`のメモリ確保
3. **44-49行目**: メトリクス用ミューテックスの初期化
4. **51-57行目**: タイマーヒープと各種キューの初期化
5. **59-77行目**: カウンタ、ウォッチャー、FDの初期値設定
6. **68行目**: `uv__update_time(loop)`による内部時刻キャッシュ初期化
7. **79-81行目**: `uv__platform_loop_init(loop)`によるプラットフォームバックエンド初期化
8. **83-87行目**: シグナルとプロセス管理の初期化
9. **89-99行目**: cloexecロック、wqミューテックス、wq_asyncの初期化
10. **101-102行目**: wq_asyncの参照解除とINTERNALフラグ設定
11. **106-131行目**: エラー時の段階的クリーンアップ処理

#### Step 3: プラットフォーム固有バックエンドの初期化

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kqueue.c | `src/unix/kqueue.c` | macOS/BSD環境での`uv__platform_loop_init()`の実装。kqueueファイルディスクリプタの作成 |
| 3-2 | linux.c | `src/unix/linux.c` | Linux環境での`uv__platform_loop_init()`の実装。epollファイルディスクリプタの作成 |

**主要処理フロー**:
- kqueue: `kqueue()`システムコールでイベント通知用FDを作成
- epoll: `epoll_create1(O_CLOEXEC)`でイベント通知用FDを作成

#### Step 4: 内部時刻キャッシュの初期化

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | internal.h | `src/unix/internal.h` | **467-471行目**: `uv__update_time()`のインライン実装。`uv__hrtime(UV_CLOCK_FAST)`でナノ秒精度の時刻を取得し、ミリ秒に変換して`loop->time`に格納 |

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

```
uv_loop_init(loop)                      [src/unix/loop.c:30]
    |
    +-- uv__calloc()                     [src/uv-common.c:92]
    |
    +-- uv_mutex_init()                  [メトリクスlock]
    |
    +-- heap_init()                      [タイマーヒープ]
    |
    +-- uv__queue_init() x 8             [各種キュー初期化]
    |
    +-- uv__update_time(loop)            [src/unix/internal.h:467]
    |       └-- uv__hrtime()            [プラットフォーム固有]
    |
    +-- uv__platform_loop_init(loop)     [src/unix/kqueue.c or linux.c]
    |       └-- kqueue() / epoll_create1()
    |
    +-- uv__signal_global_once_init()    [シグナル初期化]
    |
    +-- uv__process_init(loop)           [プロセス管理初期化]
    |
    +-- uv_rwlock_init()                 [cloexecロック]
    |
    +-- uv_mutex_init()                  [wqミューテックス]
    |
    +-- uv_async_init(loop, &loop->wq_async, uv__work_done)
    |       └-- uv__handle_unref()       [参照カウント解除]
    |
    └-- return 0 (成功)
```

### データフロー図

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

uv_loop_t* loop     -->  memset + フィールド初期化       -->  初期化済みuv_loop_t
(未初期化)               |                                    |
                         +-- 内部フィールド確保               +-- internal_fields
                         +-- キュー・ヒープ初期化             +-- timer_heap, queues
                         +-- プラットフォーム初期化           +-- backend_fd (kqueue/epoll)
                         +-- シグナル/プロセス初期化          +-- signal/process state
                         +-- 同期プリミティブ初期化           +-- locks, mutexes
                         +-- wq_async初期化                   +-- wq_async handle
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_loop_t構造体定義・API宣言 |
| unix.h | `include/uv/unix.h` | ヘッダ | Unix固有のループプライベートフィールド定義 |
| loop.c | `src/unix/loop.c` | ソース | uv_loop_init()のUnix実装 |
| uv-common.c | `src/uv-common.c` | ソース | uv_default_loop()・uv_loop_close()等の共通実装 |
| internal.h | `src/unix/internal.h` | ヘッダ | uv__update_time()等の内部ユーティリティ |
| kqueue.c | `src/unix/kqueue.c` | ソース | macOS/BSDのuv__platform_loop_init()実装 |
| linux.c | `src/unix/linux.c` | ソース | Linuxのuv__platform_loop_init()実装 |
| heap-inl.h | `src/heap-inl.h` | ヘッダ | タイマーヒープのインライン実装 |
