# 機能設計書 14-ハンドル参照カウント制御

## 概要

`uv_ref()`/`uv_unref()`/`uv_has_ref()`によりハンドルの参照カウント（参照フラグ）を制御する機能の設計書である。

### 本機能の処理概要

**業務上の目的・背景**：libuvのイベントループは、アクティブかつ参照されている（referenced）ハンドルが存在する限り動作を続ける。本機能は、ハンドルの参照状態を制御することで、特定のハンドルがイベントループの存続判定に影響するかどうかを制御する。例えば、バックグラウンドのタイマーやウォッチャーがアクティブであっても、それだけではイベントループを存続させたくない場合に`uv_unref()`を使用する。

**機能の利用シーン**：バックグラウンドタスク（ヘルスチェック用タイマー、メトリクス収集用ハンドル等）がアクティブであっても、他のメインのハンドルがすべて完了したらイベントループを終了させたい場合に使用する。Node.jsのタイマーAPIにおけるunref()もこの仕組みに基づいている。

**主要な処理内容**：
1. `uv_ref()`: ハンドルのUV_HANDLE_REFフラグを設定し、アクティブならactive_handles_countを加算する
2. `uv_unref()`: ハンドルのUV_HANDLE_REFフラグを解除し、アクティブならactive_handles_countを減算する
3. `uv_has_ref()`: ハンドルのUV_HANDLE_REFフラグの状態を返す

**関連システム・外部連携**：イベントループの存続判定（`uv__loop_alive()`）と密接に連携する。`active_handles`カウントを通じてループの存続を制御する。

**権限による制御**：特になし。ハンドルのオーナーが呼び出す。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | ハンドル基底 | 主機能 | uv_ref()/uv_unref()/uv_has_ref()による参照カウント制御のAPI定義 |
| 2 | 設計概要 | 補助機能 | ハンドルの参照カウントによるループ存続制御の説明 |

## 機能種別

状態制御（ハンドルフラグの設定・解除・参照）

## 入力仕様

### 入力パラメータ

#### uv_ref() / uv_unref()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_handle_t* | Yes | 対象のハンドル | NULLチェックなし |

#### uv_has_ref()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | const uv_handle_t* | Yes | 対象のハンドル | NULLチェックなし |

### 入力データソース

呼び出し元から渡されるハンドル構造体ポインタ。

## 出力仕様

### 出力データ

| 関数 | 戻り値型 | 説明 |
|------|---------|------|
| uv_ref() | void | なし |
| uv_unref() | void | なし |
| uv_has_ref() | int | 参照されていれば非ゼロ、されていなければ0 |

### 出力先

`uv_has_ref()`は戻り値。`uv_ref()`/`uv_unref()`はハンドル構造体のflagsフィールドおよびループのactive_handlesを更新。

## 処理フロー

### 処理シーケンス

```
uv_ref(handle):
1. UV_HANDLE_REFフラグが既にセットされていれば何もしない
2. UV_HANDLE_REFフラグをセットする
3. UV_HANDLE_CLOSINGフラグがセットされていれば終了
4. UV_HANDLE_ACTIVEフラグがセットされていればactive_handle_add

uv_unref(handle):
1. UV_HANDLE_REFフラグがセットされていなければ何もしない
2. UV_HANDLE_REFフラグを解除する
3. UV_HANDLE_CLOSINGフラグがセットされていれば終了
4. UV_HANDLE_ACTIVEフラグがセットされていればactive_handle_rm

uv_has_ref(handle):
1. UV_HANDLE_REFフラグの状態を返す
```

### フローチャート

```mermaid
flowchart TD
    subgraph ref["uv_ref()"]
        A1[呼び出し] --> B1{REFフラグあり?}
        B1 -->|Yes| C1[何もしない]
        B1 -->|No| D1[REFフラグセット]
        D1 --> E1{CLOSINGフラグ?}
        E1 -->|Yes| F1[終了]
        E1 -->|No| G1{ACTIVEフラグ?}
        G1 -->|Yes| H1[active_handle_add]
        G1 -->|No| F1
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | デフォルト参照 | ハンドルは初期化時にデフォルトでref状態（UV_HANDLE_REF）となる | ハンドル初期化時 |
| BR-14-02 | ループ存続影響 | ref状態かつactive状態のハンドルのみがactive_handlesカウントに含まれる | 常時 |
| BR-14-03 | クローズ中無視 | ハンドルがクローズ中の場合、ref/unrefはactive_handlesカウントに影響しない | CLOSINGフラグセット時 |
| BR-14-04 | 冪等性 | 既にref状態のハンドルに対するuv_ref()は何もしない（unrefも同様） | 常時 |

### 計算ロジック

`uv__active_handle_add(h)`: `(h)->loop->active_handles++`
`uv__active_handle_rm(h)`: `(h)->loop->active_handles--`

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

該当なし。

## エラー処理

### エラーケース一覧

本関数群はエラーを返さない。

### リトライ仕様

リトライ不要。

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

該当なし。

## パフォーマンス要件

O(1)の定数時間操作。フラグのビット操作とカウンタの加減算のみ。

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

特になし。

## 備考

- ハンドル初期化マクロ`uv__handle_init()`で`flags = UV_HANDLE_REF`と設定されるため、全ハンドルはデフォルトでref状態
- Node.jsの`timer.unref()`はこの機能を基盤としている
- 参照: include/uv.h L313-315

---

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

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

### 推奨読解順序

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

ハンドルフラグの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv-common.h | `src/uv-common.h` | **L80-85**: ハンドルフラグ定義。UV_HANDLE_CLOSING(0x01), UV_HANDLE_CLOSED(0x02), UV_HANDLE_ACTIVE(0x04), UV_HANDLE_REF(0x08) |
| 1-2 | uv.h | `include/uv.h` | **L463-476**: UV_HANDLE_FIELDSマクロ。dataフィールド、loopポインタ、type、flags等 |

**読解のコツ**: `flags`フィールドはビットフラグとして使用され、各ビットが独立した状態を表す。UV_HANDLE_REF(0x08)はビット3に対応する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | **L313-315**: uv_ref()/uv_unref()/uv_has_ref()のAPI宣言 |
| 2-2 | uv-common.c | `src/uv-common.c` | **L623-635**: 公開API実装。内部マクロuv__handle_ref/uv__handle_unref/uv__has_refに委譲 |

**主要処理フロー**:
1. **623行目**: `uv_ref()` → `uv__handle_ref(handle)` を呼ぶ
2. **628行目**: `uv_unref()` → `uv__handle_unref(handle)` を呼ぶ
3. **633行目**: `uv_has_ref()` → `uv__has_ref(handle)` を呼ぶ

#### Step 3: 内部マクロの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | uv-common.h | `src/uv-common.h` | **L304-323**: uv__handle_ref/uv__handle_unref/uv__has_refマクロの定義 |
| 3-2 | uv-common.h | `src/uv-common.h` | **L331-339**: uv__handle_initマクロ。初期flagsにUV_HANDLE_REFがセットされる |

**主要処理フロー（uv__handle_ref）**:
- **306行目**: REFフラグが既にあればbreak
- **307行目**: REFフラグをセット
- **308行目**: CLOSINGフラグがあればbreak
- **309行目**: ACTIVEフラグがあればuv__active_handle_add

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

```
uv_ref(handle)              [src/uv-common.c:623]
    └─ uv__handle_ref(h)    [src/uv-common.h:304 マクロ]
         ├─ フラグチェック・セット
         └─ uv__active_handle_add(h)  [loop->active_handles++]

uv_unref(handle)             [src/uv-common.c:628]
    └─ uv__handle_unref(h)   [src/uv-common.h:313 マクロ]
         ├─ フラグチェック・解除
         └─ uv__active_handle_rm(h)  [loop->active_handles--]

uv_has_ref(handle)           [src/uv-common.c:633]
    └─ uv__has_ref(h)        [src/uv-common.h:322 マクロ]
         └─ (h->flags & UV_HANDLE_REF) != 0
```

### データフロー図

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

uv_handle_t* ──────> フラグ操作 ──────────────────> handle->flags 更新
                     ├─ UV_HANDLE_REF セット/解除    loop->active_handles 更新
                     └─ active_handles 加減算
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | 公開API宣言（L313-315） |
| uv-common.c | `src/uv-common.c` | ソース | 公開API実装（L623-635） |
| uv-common.h | `src/uv-common.h` | ヘッダ | 内部マクロ定義（L304-339） |
