# 機能設計書 80-タイマー開始

## 概要

uv_timer_start()によりタイマーを開始する（タイムアウトとリピート間隔を指定）機能の設計書である。

### 本機能の処理概要

uv_timer_start()は、タイマーハンドルを開始し、指定されたタイムアウト後にコールバック関数を呼び出す。リピート間隔が設定されている場合、タイマーは繰り返し発火する。タイマーはバイナリminヒープで管理され、発火時刻が最も近いタイマーが効率的に取り出される。

**業務上の目的・背景**：非同期プログラミングにおける時間ベースのイベントスケジューリングの基盤である。HTTPリクエストのタイムアウト、定期的なヘルスチェック、UIアニメーション制御など、時間に基づくイベント処理はあらゆるアプリケーションで必要となる。libuvのタイマーは、O(log n)の挿入性能を持つminヒープにより、大量のタイマーを効率的に管理する。

**機能の利用シーン**：
- 接続タイムアウトの設定
- 定期的なポーリング（キープアライブ等）
- デバウンス処理（最後のイベントからN ms後に実行）
- setTimeout/setIntervalの内部実装（Node.js）

**主要な処理内容**：
1. パラメータバリデーション（クローズ中チェック、コールバック非NULL）
2. 既にアクティブなタイマーを停止（uv_timer_stop()）
3. 発火時刻を計算（loop->time + timeout、オーバーフロー防御付き）
4. コールバック、タイムアウト、リピート間隔を設定
5. start_idを割り当て（同一タイムアウトでの順序保証用）
6. タイマーヒープにノードを挿入
7. ハンドルをアクティブ状態にする

**関連システム・外部連携**：イベントループの内部時刻キャッシュ（loop->time）。

**権限による制御**：特段の権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | タイマー | 主機能 | uv_timer_start()によるタイマー開始のAPI定義 |

## 機能種別

タイマー制御処理 - タイマーの開始とスケジューリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handle | uv_timer_t* | Yes | タイマーハンドル | 初期化済みかつクローズ中でないこと |
| cb | uv_timer_cb | Yes | タイマー発火時のコールバック | NULLでないこと |
| timeout | uint64_t | Yes | 最初の発火までの時間（ミリ秒） | 0以上（0で即座に発火） |
| repeat | uint64_t | Yes | リピート間隔（ミリ秒） | 0でワンショット、正値でリピート |

### 入力データソース

関数呼び出し時の引数として渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時0、失敗時UV_EINVAL |
| handle->timer_cb | uv_timer_cb | 設定されたコールバック |
| handle->timeout | uint64_t | 絶対発火時刻（loop->time + timeout） |
| handle->repeat | uint64_t | リピート間隔 |
| handle->start_id | uint64_t | 順序保証用のID |

### 出力先

タイマーハンドルが更新され、タイマーヒープに挿入される。

## 処理フロー

### 処理シーケンス

```
1. バリデーション
   └─ クローズ中またはcb==NULLの場合、UV_EINVALを返す

2. 既存タイマーの停止
   └─ uv_timer_stop(handle)を呼び出し（ヒープからの除去）

3. 発火時刻の計算
   ├─ clamped_timeout = loop->time + timeout
   └─ オーバーフロー時は(uint64_t)-1にクランプ

4. フィールド設定
   ├─ handle->timer_cb = cb
   ├─ handle->timeout = clamped_timeout
   ├─ handle->repeat = repeat
   └─ handle->start_id = loop->timer_counter++

5. ヒープ挿入
   └─ heap_insert(timer_heap, &handle->node.heap, timer_less_than)

6. ハンドルのアクティブ化
   └─ uv__handle_start(handle)

7. return 0
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{closing or cb==NULL?}
    B -->|Yes| C[return UV_EINVAL]
    B -->|No| D[uv_timer_stop]
    D --> E[clamped_timeout = loop->time + timeout]
    E --> F{オーバーフロー?}
    F -->|Yes| G[clamped_timeout = UINT64_MAX]
    F -->|No| H[timer_cb, timeout, repeat設定]
    G --> H
    H --> I[start_id = timer_counter++]
    I --> J[heap_insert]
    J --> K[uv__handle_start]
    K --> L[return 0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | 再開始可能 | 既にアクティブなタイマーにuv_timer_start()を再度呼び出すと、先に停止してから新しい設定で開始する | 常時 |
| BR-80-02 | オーバーフロー防御 | loop->time + timeoutがオーバーフローする場合、UINT64_MAXにクランプする | タイムアウト値が非常に大きい場合 |
| BR-80-03 | 順序保証 | 同じタイムアウト値を持つタイマーはstart_id（割り当て順）で順序付けされる | 複数タイマーが同時刻に発火する場合 |
| BR-80-04 | timeout=0で即座発火 | timeout=0の場合、次のイベントループイテレーションで発火する | timeout == 0 |
| BR-80-05 | repeat=0でワンショット | repeat=0の場合、一度だけ発火し自動的に停止する | repeat == 0 |

### 計算ロジック

発火時刻の計算:
- `clamped_timeout = handle->loop->time + timeout`
- `if (clamped_timeout < timeout) clamped_timeout = (uint64_t) -1` （オーバーフロー検出）

ヒープの順序比較（timer_less_than）:
- 第一キー: timeout（発火時刻）が小さい方が優先
- 第二キー: start_id（割り当て順）が小さい方が優先

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータエラー | handleがクローズ中またはcbがNULL | 有効なハンドルとコールバックを指定する |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

ヒープ挿入操作はO(log n)で実行される。タイマー発火処理（uv__run_timers）では、ヒープの最小要素の取得がO(1)で行われる。

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

- オーバーフロー防御によりタイムアウト値の不正操作を防止
- timer_counterはモノトニックに増加し、巻き戻ることはない

## 備考

- タイマー発火はuv__run_timers()（src/timer.c L164-194）で処理される
- リピートタイマーは発火後にuv_timer_again()で自動的に再スケジュールされる
- start_idはloop->timer_counterからインクリメントで割り当てられ、同一タイムアウトでのFIFO順序を保証する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L977-980**: uv_timer_start()のAPI宣言 |
| 1-2 | heap-inl.h | `src/heap-inl.h` | **L40-43**: ヒープ構造体。min（ルートノード）とnelts（要素数）で構成 |

**読解のコツ**: タイマーのnodeフィールドはheapとqueueのunionであり、アクティブ時はheapとして、停止時はqueueとして使用される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | timer.c | `src/timer.c` | **L67-94**: uv_timer_start()の全実装 |

**主要処理フロー**:
1. **73-74行目**: クローズ中/cb==NULLチェック -> UV_EINVAL
2. **76行目**: uv_timer_stop()で既存タイマー停止
3. **78-80行目**: clamped_timeoutの計算（オーバーフロー防御）
4. **82-84行目**: timer_cb, timeout, repeat設定
5. **86行目**: start_id = loop->timer_counter++
6. **88-90行目**: heap_insert()でヒープに挿入
7. **91行目**: uv__handle_start()
8. **93行目**: return 0

#### Step 3: ヒープ挿入操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | heap-inl.h | `src/heap-inl.h` | **L106-148**: heap_insert()。挿入位置の計算 -> ノード配置 -> 上方向のバブルアップ |

#### Step 4: タイマー発火処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | timer.c | `src/timer.c` | **L164-194**: uv__run_timers()。ヒープから期限切れタイマーを取り出し、コールバックを呼び出す |

**主要処理フロー**:
1. **172-183行目**: ヒープから期限切れタイマーをready_queueに移動
2. **185-193行目**: ready_queueの各タイマーに対してuv_timer_again()とtimer_cb()を呼び出し

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

```
uv_timer_start(handle, cb, timeout, repeat)  [src/timer.c L67]
    +-- uv_timer_stop(handle)                 [既存タイマー停止 L97]
    |   +-- heap_remove()                     [ヒープから除去]
    |   +-- uv__handle_stop()
    +-- heap_insert(timer_heap, node, timer_less_than)  [src/heap-inl.h L106]
    +-- uv__handle_start(handle)

[タイマー発火時]
uv__run_timers(loop)                          [src/timer.c L164]
    +-- heap_min(timer_heap)                  [最小タイマー取得]
    +-- uv_timer_stop(handle)                 [停止]
    +-- uv_timer_again(handle)                [リピート時再スケジュール]
    +-- handle->timer_cb(handle)              [コールバック呼び出し]
```

### データフロー図

```
[入力]                    [処理]                         [出力]
cb (コールバック) -------> フィールド設定 ---------------> handle->timer_cb
timeout (ミリ秒) -------> loop->time + timeout ---------> handle->timeout (絶対時刻)
repeat (ミリ秒) ---------> フィールド設定 ---------------> handle->repeat
                          heap_insert() -----------------> タイマーヒープに挿入
                          uv__handle_start() ------------> ハンドルアクティブ化
                                                    ----> 戻り値 (0 or UV_EINVAL)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_timer_start()宣言（L977-980） |
| timer.c | `src/timer.c` | ソース | uv_timer_start()実装（L67-94）、uv__run_timers()（L164-194）、timer_less_than()（L37-54） |
| heap-inl.h | `src/heap-inl.h` | ヘッダ | バイナリminヒープ実装（heap_insert L106-148） |
| uv-common.h | `src/uv-common.h` | ヘッダ | 共通定義 |
