# 機能設計書 137-ワンスガード

## 概要

uv_once()により関数を一度だけ実行するワンスガードを提供する機能の設計書である。

### 本機能の処理概要

本機能は、複数スレッドから同時に呼び出されても指定されたコールバック関数をプロセス全体で一度だけ実行することを保証するワンスガードのクロスプラットフォームAPIを提供する。

**業務上の目的・背景**：シングルトンパターンの初期化、グローバルリソースの遅延初期化（Lazy Initialization）、ライブラリの初期化処理など、「初回のみ実行」が必要なパターンはマルチスレッドプログラミングで頻出する。手動でのフラグ管理はレースコンディションの温床となるため、OS提供の原子的なワンスガード機構が必要である。libuvはPOSIXのpthread_onceとWindowsのInitOnceExecuteOnceの差異を吸収する。

**機能の利用シーン**：グローバル設定の遅延初期化、TLSキーの一度きりの作成（libuv内部のuv__init_current_thread_keyなど）、ライブラリのセットアップ処理、シングルトンオブジェクトの生成に利用される。libuv内部ではglibc_version_check_once、uv__current_thread_init_guard、uv__thread_name_onceなどで広く使用されている。

**主要な処理内容**：
1. uv_once()によるコールバック関数の一度きりの実行保証

**関連システム・外部連携**：Unix系ではpthread_once()、WindowsではInitOnceExecuteOnce()を使用する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | スレッド | 主機能 | uv_once()による一度だけ実行保証のAPI定義 |

## 機能種別

同期プリミティブ操作（ワンスガード）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| guard | uv_once_t* | Yes | ワンスガードオブジェクト（UV_ONCE_INITで静的初期化） | NULLの場合は未定義動作 |
| callback | void (*)(void) | Yes | 一度だけ実行するコールバック関数 | NULLの場合は未定義動作 |

### 入力データソース

呼び出し元アプリケーションからの直接指定。guardはグローバル変数として静的に初期化する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | なし（失敗時abort()） |

### 出力先

なし（副作用としてコールバック関数が実行される）。

## 処理フロー

### 処理シーケンス

```
uv_once():
1. [Unix] pthread_once(guard, callback)
   └─ 失敗時abort()
2. [Windows]
   a. uv__once_data_t構造体にcallbackを格納
   b. InitOnceExecuteOnce(&guard->init_once, uv__once_inner, &data, NULL)
   c. uv__once_inner内でdata->callback()を実行
```

### フローチャート

```mermaid
flowchart TD
    A[uv_once呼び出し] --> B{既に実行済み?}
    B -->|Yes| C[即座に返却]
    B -->|No| D{他スレッドが実行中?}
    D -->|Yes| E[完了まで待機]
    E --> C
    D -->|No| F[コールバック実行]
    F --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-137-01 | 一度きり実行 | callbackは全スレッドを通じて正確に1回だけ実行される | 常時 |
| BR-137-02 | 静的初期化 | guardはUV_ONCE_INITマクロで静的に初期化する必要がある | 常時 |
| BR-137-03 | ブロッキング | 他スレッドがcallbackを実行中の場合、呼び出しスレッドはその完了まで待機する | 同時呼び出し時 |
| BR-137-04 | 致命的エラー | Unix版でpthread_onceが失敗した場合abort() | Unix環境 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| abort() | 致命的エラー | Unix版でpthread_onceが失敗 | guardの初期化状態を確認 |

### リトライ仕様

リトライは不要。一度成功した後の再呼び出しは即座に返却される。

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

該当なし。

## パフォーマンス要件

初回実行時のみOS同期機構のオーバーヘッドがかかる。2回目以降はアトミック変数チェックのみで即座に返却されるため、実質ゼロコスト。

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

特になし。

## 備考

- UV_ONCE_INITはUnixではPTHREAD_ONCE_INIT、Windowsでは{INIT_ONCE_STATIC_INIT}に展開される。
- Windows版では関数ポインタの型差異を吸収するためuv__once_data_t構造体とuv__once_inner()ラッパー関数が使用されている。
- uv_once()のguardを動的に確保・初期化する方法は提供されていないため、必ずグローバルまたはstatic変数として宣言する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unix.h | `include/uv/unix.h` | uv_once_tの型定義（L129: pthread_once_t） |
| 1-2 | win.h | `include/uv/win.h` | uv_once_tの構造体定義（L287: INIT_ONCE init_once含む） |
| 1-3 | uv.h | `include/uv.h` | API宣言（L1883） |

**読解のコツ**: uv_once_tはUnixではpthread_once_tの直接typedef、Windowsでは INIT_ONCEを含む構造体。UV_ONCE_INITマクロでの初期化が必須。

#### Step 2: Unix版実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread.c (Unix) | `src/unix/thread.c` | uv_once()（L453-456） |

**主要処理フロー**:
- **L453-456**: pthread_once(guard, callback)を呼び出し、失敗時abort()。極めてシンプルな実装。

#### Step 3: Windows版実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | thread.c (Win) | `src/win/thread.c` | uv__once_data_t型定義とuv__once_inner()（L37-47） |
| 3-2 | thread.c (Win) | `src/win/thread.c` | uv_once()（L49-52） |

**主要処理フロー**:
- **L37-39**: uv__once_data_tはcallback関数ポインタを保持する構造体
- **L41-47**: uv__once_innerはINIT_ONCEコールバック形式に適合するラッパー。data->callback()を呼び出しTRUEを返す
- **L49-52**: uv_once()はuv__once_data_tにcallbackを格納し、InitOnceExecuteOnce()に渡す

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

```
uv_once(guard, callback)
    |
    +-- [Unix] pthread_once(guard, callback)
    |          → 失敗: abort()
    |
    +-- [Windows]
            +-- uv__once_data_t data = { .callback = callback }
            +-- InitOnceExecuteOnce(&guard->init_once, uv__once_inner, &data, NULL)
                    +-- uv__once_inner(once, param, context)
                            +-- data->callback()
                            +-- return TRUE
```

### データフロー図

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

guard (uv_once_t*)      --> OS原子的実行保証       --> callback()が1回だけ実行
callback (void(*)())        pthread_once /              副作用による初期化完了
                            InitOnceExecuteOnce
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言（L1883） |
| unix.h | `include/uv/unix.h` | ヘッダ | uv_once_t型定義（L129） |
| win.h | `include/uv/win.h` | ヘッダ | uv_once_t型定義（L287） |
| thread.c (Unix) | `src/unix/thread.c` | ソース | Unix版実装（L453-456） |
| thread.c (Win) | `src/win/thread.c` | ソース | Windows版実装（L37-52） |
