# アーキテクチャ設計書

## 概要

本ドキュメントは、libuv（バージョン1.52.1-dev）のアーキテクチャ設計を記載する。libuvは、Node.jsのために開発されたマルチプラットフォーム対応の非同期I/Oライブラリであり、イベント駆動型アーキテクチャに基づくイベントループを中核としている。C言語（C11標準）で実装され、Windows、Linux、macOS、FreeBSD、AIX等の主要OSをサポートする。本書では、アプリケーション構造、レイヤー構成、モジュール構成、データフロー、横断的関心事について詳述する。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図](./アーキテクチャ構成図.md) を参照。

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| OSカーネル（epoll/kqueue/IOCP/event ports） | システムコール | I/Oイベント多重化（I/O polling） |
| POSIX スレッドライブラリ（pthread） | C API | スレッドプール管理、同期プリミティブ |
| Windows API（IOCP, WinSock2等） | Win32 API | Windows環境でのI/O完了ポート・ソケット操作 |
| ファイルシステム | システムコール | ファイル操作（read/write/stat等） |
| ネットワークスタック | ソケットAPI | TCP/UDP/パイプ通信 |
| DNS resolver | getaddrinfo/getnameinfo | 名前解決 |
| Linux io_uring | システムコール | Linux環境での高速非同期I/O（オプション） |
| FSEvents（macOS） | Core Services API | macOS環境でのファイルシステムイベント監視 |
| inotify（Linux） | システムコール | Linux環境でのファイルシステムイベント監視 |

## レイヤー構成

### アーキテクチャスタイル

**レイヤードアーキテクチャ + プラットフォーム抽象化パターン（HAL: Hardware Abstraction Layer）**

libuvは3層のレイヤードアーキテクチャを採用し、パブリックAPIレイヤー、共通実装レイヤー、プラットフォーム固有実装レイヤーに分離される。プラットフォーム固有の差異は、プラットフォーム抽象化パターンにより吸収され、上位レイヤーに対して統一されたインターフェースを提供する。

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| パブリックAPI層 | 外部利用者へのインターフェース提供。ハンドル型・リクエスト型・コールバック型の定義 | `include/uv.h`, `include/uv/*.h` |
| 共通実装層（Cross-platform） | プラットフォーム非依存のロジック実装。タイマー管理、スレッドプール、メモリ管理、エラー処理 | `src/uv-common.c`, `src/uv-common.h`, `src/timer.c`, `src/threadpool.c`, `src/heap-inl.h`, `src/queue.h`, `src/fs-poll.c`, `src/inet.c`, `src/idna.c`, `src/random.c`, `src/version.c` |
| プラットフォーム固有実装層 | OS固有のシステムコール・APIを使用したI/O、プロセス管理、ファイルシステム操作の実装 | `src/unix/`（Unix系全般）, `src/win/`（Windows） |

### レイヤー間の依存関係ルール

- **パブリックAPI層** は、共通実装層およびプラットフォーム固有実装層の具体的な実装に依存しない。ヘッダファイルでは構造体のレイアウトのみをプラットフォーム別に切り替える（`UV_HANDLE_PRIVATE_FIELDS`マクロ等）。
- **共通実装層** は、パブリックAPI層のヘッダ（`uv.h`）をインクルードし、プラットフォーム固有実装層の内部ヘッダ（`unix/internal.h` または `win/internal.h`）を必要に応じてインクルードする。
- **プラットフォーム固有実装層** は、共通実装層のヘッダ（`uv-common.h`）をインクルードし、共通のマクロやユーティリティ関数を利用する。
- **禁止される参照**: プラットフォーム固有実装層間の相互参照（Unix実装からWindows実装への参照、およびその逆）は禁止されている。コンパイル時に`#if defined(_WIN32)`等の条件コンパイルで排他的に選択される。

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| イベントループ（Event Loop） | イベントループのライフサイクル管理、I/Oポーリング、コールバックディスパッチ | `src/unix/core.c`, `src/unix/loop.c`, `src/win/core.c` |
| ネットワークI/O | TCP/UDP/パイプ接続・通信処理 | `src/unix/tcp.c`, `src/unix/udp.c`, `src/unix/pipe.c`, `src/unix/stream.c`, `src/win/tcp.c`, `src/win/udp.c`, `src/win/pipe.c` |
| ファイルシステム | 非同期ファイル操作（read/write/stat/mkdir等） | `src/unix/fs.c`, `src/win/fs.c`, `src/fs-poll.c` |
| タイマー | タイムアウト管理、周期的コールバック | `src/timer.c`, `src/heap-inl.h` |
| スレッドプール | ブロッキングI/Oの非同期化、ワーカースレッド管理 | `src/threadpool.c`, `src/thread-common.c` |
| プロセス管理 | 子プロセスの起動・監視・終了処理 | `src/unix/process.c`, `src/win/process.c` |
| シグナル処理 | Unixシグナルのイベントループへの統合 | `src/unix/signal.c`, `src/win/signal.c` |
| ファイルシステムイベント | ファイル変更の監視（inotify/FSEvents/kqueue等） | `src/unix/fsevents.c`, `src/unix/kqueue.c`, `src/unix/linux.c`, `src/win/fs-event.c` |
| DNS解決 | getaddrinfo/getnameinfoの非同期ラッパー | `src/unix/getaddrinfo.c`, `src/unix/getnameinfo.c`, `src/win/getaddrinfo.c` |
| TTY制御 | 端末制御・ANSI処理 | `src/unix/tty.c`, `src/win/tty.c` |
| 動的ライブラリ | 共有ライブラリのロード・シンボル解決 | `src/unix/dl.c`, `src/win/dl.c` |
| 乱数生成 | 暗号学的に安全な乱数生成 | `src/random.c`, `src/unix/random-*.c` |
| ユーティリティ | 文字列操作、IDNA、INETアドレス変換 | `src/idna.c`, `src/inet.c`, `src/strscpy.c`, `src/strtok.c` |

### パッケージ構造

```
libuv-1.x/
├── include/
│   ├── uv.h                    # メインパブリックAPI（全ハンドル型・リクエスト型・関数宣言）
│   └── uv/
│       ├── errno.h             # エラーコード定義
│       ├── version.h           # バージョン定義
│       ├── unix.h              # Unix固有の構造体フィールド定義
│       ├── win.h               # Windows固有の構造体フィールド定義
│       ├── darwin.h            # macOS固有定義
│       ├── linux.h             # Linux固有定義
│       ├── bsd.h               # BSD固有定義
│       ├── aix.h               # AIX固有定義
│       ├── sunos.h             # SunOS固有定義
│       ├── os390.h             # z/OS固有定義
│       ├── posix.h             # POSIX汎用定義
│       ├── tree.h              # 赤黒木データ構造
│       └── threadpool.h        # スレッドプール構造体定義
├── src/
│   ├── uv-common.c             # プラットフォーム共通実装（メモリ管理、エラー処理等）
│   ├── uv-common.h             # 共通内部ヘッダ（ハンドルフラグ、マクロ定義）
│   ├── uv-data-getter-setters.c # データアクセサ関数
│   ├── timer.c                 # タイマー管理（ヒープベース）
│   ├── threadpool.c            # スレッドプール実装
│   ├── thread-common.c         # スレッド共通処理
│   ├── fs-poll.c               # ファイルシステムポーリング
│   ├── heap-inl.h              # 二分最小ヒープ（タイマー用）
│   ├── queue.h                 # 侵入型双方向連結リスト
│   ├── random.c                # 乱数生成エントリポイント
│   ├── inet.c                  # IPアドレス変換
│   ├── idna.c                  # IDNA（国際化ドメイン名）処理
│   ├── strscpy.c               # 安全な文字列コピー
│   ├── strtok.c                # 文字列トークナイザ
│   ├── version.c               # バージョン情報
│   ├── unix/                   # Unix系プラットフォーム固有実装
│   │   ├── core.c              # イベントループ本体（uv_run）
│   │   ├── loop.c              # ループ初期化・終了
│   │   ├── internal.h          # Unix内部ヘッダ
│   │   ├── async.c             # 非同期通知
│   │   ├── stream.c            # ストリーム抽象化
│   │   ├── tcp.c               # TCP実装
│   │   ├── udp.c               # UDP実装
│   │   ├── pipe.c              # パイプ実装
│   │   ├── process.c           # プロセス管理
│   │   ├── signal.c            # シグナル処理
│   │   ├── fs.c                # ファイルシステム操作
│   │   ├── poll.c              # ファイルディスクリプタポーリング
│   │   ├── tty.c               # TTY制御
│   │   ├── dl.c                # 動的ライブラリ
│   │   ├── thread.c            # スレッド操作
│   │   ├── loop-watcher.c      # idle/prepare/checkハンドル
│   │   ├── getaddrinfo.c       # DNS正引き
│   │   ├── getnameinfo.c       # DNS逆引き
│   │   ├── kqueue.c            # kqueue I/Oバックエンド
│   │   ├── linux.c             # Linux固有実装（epoll, io_uring）
│   │   ├── darwin.c            # macOS固有実装
│   │   ├── fsevents.c          # macOS FSEvents
│   │   ├── freebsd.c           # FreeBSD固有実装
│   │   ├── netbsd.c            # NetBSD固有実装
│   │   ├── openbsd.c           # OpenBSD固有実装
│   │   ├── sunos.c             # SunOS/Solaris固有実装
│   │   ├── aix.c               # AIX固有実装
│   │   ├── os390.c             # z/OS固有実装
│   │   └── ...                 # その他プラットフォーム固有ファイル
│   └── win/                    # Windows固有実装
│       ├── core.c              # イベントループ本体（uv_run）
│       ├── internal.h          # Windows内部ヘッダ
│       ├── async.c             # 非同期通知
│       ├── stream.c            # ストリーム抽象化
│       ├── tcp.c               # TCP実装
│       ├── udp.c               # UDP実装
│       ├── pipe.c              # パイプ実装
│       ├── process.c           # プロセス管理
│       ├── signal.c            # シグナル処理
│       ├── fs.c                # ファイルシステム操作
│       ├── fs-event.c          # ファイルシステムイベント
│       ├── tty.c               # TTY制御
│       ├── dl.c                # 動的ライブラリ
│       ├── thread.c            # スレッド操作
│       ├── poll.c              # ポーリング
│       ├── handle.c            # ハンドル管理
│       ├── winapi.c            # Windows API動的ロード
│       ├── winsock.c           # WinSockユーティリティ
│       ├── util.c              # ユーティリティ
│       └── ...                 # その他Windows固有ファイル
└── test/                       # テストコード
    ├── test-*.c                # 個別テスト
    ├── benchmark-*.c           # ベンチマーク
    └── runner*.c               # テストランナー
```

### コンポーネント依存関係

libuvの主要コンポーネント間の依存関係は以下の通りである。

1. **イベントループ (`uv_loop_t`)** はシステムの中核であり、全てのハンドルとリクエストはイベントループに属する。
2. **ハンドル (`uv_handle_t`)** はイベントループに登録され、アクティブな間はイベントループの存続を維持する。ハンドルの基底型（`uv_handle_t`）から派生型（`uv_tcp_t`, `uv_timer_t`等）が継承する。
3. **ストリーム (`uv_stream_t`)** はハンドルの派生型であり、TCP、パイプ、TTYの基底型となる。読み書き操作の共通インターフェースを提供する。
4. **リクエスト (`uv_req_t`)** は一回限りの非同期操作を表現する。ファイルシステム操作（`uv_fs_t`）、DNS解決（`uv_getaddrinfo_t`）等がある。
5. **スレッドプール** はブロッキング操作（FS操作、DNS解決、乱数生成等）をワーカースレッドで実行し、完了時にイベントループのコールバックキューに結果を返す。
6. **タイマーヒープ** は二分最小ヒープで管理され、イベントループの各反復でタイムアウトしたタイマーのコールバックが実行される。

## ミドルウェア構成

### データベース

libuvはデータベースを直接使用しない。libuvはI/Oライブラリであり、データベース接続はlibuvを利用するアプリケーション側の責務である。

### キャッシュ

libuvはキャッシュミドルウェアを使用しない。ただし、内部的にプラットフォーム情報のキャッシュ（例: `IOV_MAX`のアトミックキャッシュ）を行う箇所がある。

### メッセージキュー

libuvはメッセージキューミドルウェアを使用しない。ただし、内部的に以下のキューイングメカニズムを持つ。

| 内部キュー | 用途 |
| --- | --- |
| `wq`（ワークキュー） | スレッドプールのタスクキュー。CPUバウンドタスクとスローI/Oタスクを管理 |
| `slow_io_pending_wq` | スローI/O専用の待機キュー。同時実行数を制限して過負荷を防止 |
| `pending_queue` | I/Oポーリング後に処理待ちのコールバックキュー |
| `handle_queue` | ループに登録されたハンドルのキュー |
| `watcher_queue` | I/Oウォッチャーの登録・更新キュー |

### 検索エンジン

該当なし。libuvは検索エンジンを使用しない。

### その他ミドルウェア

| ミドルウェア | 用途 |
| --- | --- |
| OSのI/O多重化機構 | epoll（Linux）、kqueue（macOS/BSD）、IOCP（Windows）、event ports（SunOS）をバックエンドとして使用 |
| io_uring（Linux、オプション） | Linux 5.1以降で利用可能な高性能非同期I/Oインターフェース。`UV_LOOP_USE_IO_URING_SQPOLL`オプションで有効化 |

## データフロー

### リクエスト処理の流れ

イベントループ（`uv_run`）の1回の反復における処理フローは以下の通りである。

1. **ループ存続判定** (`uv__loop_alive`): アクティブなハンドルまたはリクエストが存在するかを確認する
2. **時刻更新** (`uv__update_time`): 高精度タイマーからループの現在時刻を更新する
3. **タイマー実行** (`uv__run_timers`): タイムアウトしたタイマーのコールバックをヒープから取り出して実行する
4. **保留中コールバック実行** (`uv__run_pending`): 前回のI/Oポーリングで発生したコールバックを処理する
5. **idle ハンドル実行** (`uv__run_idle`): idle コールバックを実行する
6. **prepare ハンドル実行** (`uv__run_prepare`): I/Oポーリング前の準備コールバックを実行する
7. **I/Oポーリング** (`uv__io_poll`): epoll/kqueue/IOCP等を使用してI/Oイベントを待機する。タイムアウトはタイマーヒープの最小値から算出される
8. **I/O後の保留中コールバック** (`uv__run_pending`): I/Oポーリングで発生したコールバックを最大8回処理する（ループ飢餓防止）
9. **アイドル時間更新** (`uv__metrics_update_idle_time`): メトリクス用のアイドル時間を更新する
10. **check ハンドル実行** (`uv__run_check`): I/Oポーリング後のチェックコールバックを実行する
11. **クローズ処理** (`uv__run_closing_handles`): クローズ待ちのハンドルのクローズコールバックを実行する
12. **時刻再更新 + タイマー再実行**: ループの最後にタイマーを再評価する

### 非同期処理の流れ

ブロッキング操作（ファイルシステム操作、DNS解決等）のスレッドプールを介した非同期処理フロー。

1. **リクエスト登録**: アプリケーションが非同期APIを呼び出す（例: `uv_fs_read`, `uv_getaddrinfo`）
2. **ワーク投入** (`uv__work_submit`): リクエストをスレッドプールのワークキュー（`wq`）に投入する。スローI/O（`UV__WORK_SLOW_IO`）は専用キューに投入され、同時実行スレッド数が`(nthreads + 1) / 2`に制限される
3. **ワーカースレッド実行** (`worker`): ワーカースレッドがキューからタスクを取り出し、ブロッキング操作を実行する
4. **完了通知**: ワーカースレッドが完了した作業をループの完了キュー（`loop->wq`）に投入し、`uv_async_send`でイベントループに通知する
5. **コールバック実行** (`uv__work_done`): イベントループがI/Oポーリングで通知を受け取り、完了コールバックをイベントループのスレッドで実行する

### データ永続化の流れ

libuvはデータ永続化層を持たない。ファイルシステム操作（`uv_fs_*` API群）はOSのファイルシステムへの薄いラッパーであり、以下のフローで処理される。

1. **同期モード**: コールバック関数に`NULL`を渡すと、呼び出しスレッドで直接システムコールを実行し、結果を即座に返す
2. **非同期モード**: コールバック関数を渡すと、スレッドプールにファイル操作を委譲し、完了時にイベントループでコールバックを実行する
3. **io_uringモード（Linux）**: 対応するファイル操作（open, read, write, close, stat, rename, unlink等）はio_uringを通じてカーネルに直接投入される場合がある

## 横断的関心事

### 認証・認可

libuvは認証・認可機構を持たない。これらはlibuvを利用するアプリケーション層の責務である。

### ロギング・監査

libuvはロギングフレームワークを持たない。エラーはリターンコードまたはコールバックのstatusパラメータで報告される。

| 種類 | 実装方式 | 備考 |
| --- | --- | --- |
| エラー報告 | 関数戻り値（負のエラーコード） | `UV_E*`マクロで定義された統一エラーコード |
| メトリクス | `uv_metrics_t`構造体 | ループ回数、イベント数、アイドル時間を記録 |

### エラーハンドリング

libuvは統一されたエラーコード体系を持ち、全てのエラーは負の整数値として返される。

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| 同期API呼び出しエラー | 負のエラーコードを関数戻り値として返却 | `uv_strerror()`, `uv_err_name()`で文字列変換可能 |
| 非同期操作エラー | コールバックのstatusパラメータ | 0は成功、負の値はエラーコード |
| システムエラー | `UV__ERR(errno)`マクロでPOSIXエラーをlibuv統一エラーに変換 | `uv_translate_sys_error()`で変換 |
| メモリアロケーションエラー | `UV_ENOMEM`を返却、または`abort()`で停止 | スレッドプール初期化時のメモリ不足は致命的エラー |
| 致命的エラー | `abort()`によるプロセス停止 | スレッドプール初期化失敗、mutex初期化失敗等 |

### トランザクション管理

libuvはトランザクション管理を行わない。代わりに以下のリソース管理パターンを採用している。

| 範囲 | 管理方式 | 詳細 |
| --- | --- | --- |
| ハンドルライフサイクル | 参照カウント方式 | `uv_ref()`/`uv_unref()`でイベントループの存続に影響するかを制御 |
| メモリ管理 | カスタムアロケータ | `uv_replace_allocator()`で`malloc`/`realloc`/`calloc`/`free`をカスタム実装に置換可能 |
| スレッドプール同期 | mutex + 条件変数 | グローバルmutex (`mutex`) とループローカルmutex (`loop->wq_mutex`) の2段階ロックで、デッドロックを回避するプロトコルを採用 |

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| プラットフォーム抽象化 | 全モジュール | `src/unix/`と`src/win/`で同一API（`uv_tcp_init`, `uv_fs_read`等）を個別実装 |
| コールバック駆動（Reactor Pattern） | イベントループ | ハンドルにコールバック関数を登録し、イベント発生時にイベントループが呼び出す |
| 侵入型データ構造 | ハンドル・キュー管理 | `container_of`マクロによる侵入型リスト・ヒープ。外部メモリ割り当て不要 |
| ゼロコピーバッファ | I/O操作 | `uv_buf_t`は`struct iovec`とABI互換に設計され、余分なコピーを回避 |
| 遅延初期化 | スレッドプール | `uv_once(&once, init_once)`により、最初の非同期操作時にスレッドプールを初期化 |
| 単一スレッドイベントループ | イベントループ | 各イベントループは単一スレッドで動作し、コールバックは直列に実行される。スレッドセーフティは利用者の責務 |
| ハンドル/リクエスト分離 | 全API | 長命なリソース（ハンドル）と一回限りの操作（リクエスト）を型レベルで分離 |

### コーディング規約

- **言語標準**: C11（`CMAKE_C_STANDARD 11`）
- **命名規約**: パブリックAPIは`uv_`接頭辞、内部関数は`uv__`接頭辞（ダブルアンダースコア）
- **ヘッダガード**: `#ifndef UV_*_H_`形式のインクルードガード
- **エラーコード**: 全てのエラーは`UV_E*`マクロで定義された負の整数値
- **マクロ多用**: X-macros（`UV_HANDLE_TYPE_MAP`, `UV_REQ_TYPE_MAP`, `UV_ERRNO_MAP`）によるコード生成パターン
- **ビジビリティ**: `CMAKE_C_VISIBILITY_PRESET hidden`により、エクスポート関数のみ`UV_EXTERN`で公開
- **コンパイラ警告**: `-Wall -Wextra -Wstrict-prototypes`（GCC/Clang）、`/W4`（MSVC）
- **静的解析**: clang-tidyによる静的解析サポート（`ENABLE_CLANG_TIDY`オプション）
- **メモリ管理**: `uv__malloc`/`uv__free`等のラッパーを経由し、カスタムアロケータに対応
- **errno保護**: `uv__free()`はerrnoを保護する（`SAVE_ERRNO`マクロ）

## 備考

- libuvのスレッドプールサイズは環境変数`UV_THREADPOOL_SIZE`で設定可能であり、デフォルトは4、最大は1024である（`src/threadpool.c`）。ワーカースレッドのスタックサイズは8MBに設定されている。
- Linux環境ではio_uringの利用がオプションとしてサポートされており、`UV_LOOP_USE_IO_URING_SQPOLL`オプションで有効化できる。対応するファイル操作（open, read, write, close, stat, rename, symlink, unlink, mkdir, ftruncate, fsync, fdatasync, link）はio_uringを通じて処理される。
- macOS環境ではCore Services FrameworkのFSEventsをファイルシステム監視に使用し、BSD系OSではkqueueを使用する。
- libuvは共有ライブラリ（`libuv.so`/`libuv.dylib`/`uv.dll`）と静的ライブラリ（`libuv_a.a`/`libuv.lib`）の両方としてビルド可能である。
- サニタイザ（ASan, MSan, TSan, UBSan）によるビルドがCMakeオプションとしてサポートされている。
