# 機能設計書 136-バリア

## 概要

uv_barrier_init()/uv_barrier_destroy()/uv_barrier_wait()によりバリア同期プリミティブを制御する機能の設計書である。

### 本機能の処理概要

本機能は、複数のスレッドが指定された集合点（バリア）に全て到達するまで待機し、全スレッド到達後に一斉に処理を再開するための同期プリミティブを提供する。

**業務上の目的・背景**：並列処理において、複数のワーカースレッドがそれぞれの処理を完了した後に次のフェーズへ進むという同期パターンは頻出する。バリアはこのパターンを簡潔に実現する同期プリミティブである。libuvはPOSIXのpthread_barrierをサポートしないプラットフォーム（AIX、OpenBSD、Windows等）向けにmutex+condvarベースのカスタム実装を提供することで、クロスプラットフォームでの利用を可能にしている。

**機能の利用シーン**：マップリデュース処理におけるフェーズ間の同期、複数ワーカーの初期化完了待ち、テストコードにおける全スレッドの準備完了確認に利用される。

**主要な処理内容**：
1. uv_barrier_init()によるバリアの初期化（参加スレッド数を指定）
2. uv_barrier_wait()によるバリアでの待機（全スレッド到達で解放）
3. uv_barrier_destroy()によるバリアの破棄

**関連システム・外部連携**：pthread_barrierが利用可能なプラットフォームではネイティブAPIを使用し、それ以外ではuv_mutex_t + uv_cond_tによるカスタム実装を使用する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | スレッド | 主機能 | uv_barrier_init()/destroy()/wait()によるバリア同期のAPI定義 |
| 36 | スレッド | 補助機能 | バリア同期のサンプル解説 |

## 機能種別

同期プリミティブ操作（バリア同期）

## 入力仕様

### 入力パラメータ

#### uv_barrier_init()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| barrier | uv_barrier_t* | Yes | バリアオブジェクト | NULLの場合UV_EINVAL |
| count | unsigned int | Yes | 参加スレッド数 | 0の場合UV_EINVAL |

#### uv_barrier_wait() / uv_barrier_destroy()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| barrier | uv_barrier_t* | Yes | バリアオブジェクト | NULLの場合UV_EINVAL（カスタム実装時） |

### 入力データソース

呼び出し元アプリケーションからの直接指定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 (init) | int | 成功時0、失敗時負のエラーコード |
| 戻り値 (wait) | int | 最後にバリアに到達したスレッドは非0（真）、それ以外は0 |
| 戻り値 (destroy) | void | 失敗時abort() |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
uv_barrier_init() [カスタム実装]:
1. barrier/countの検証（NULLまたは0ならUV_EINVAL）
2. [Unix] _uv_barrier構造体をmalloc確保
3. in=0, out=0, threshold=countに初期化
4. uv_mutex_init() + uv_cond_init()
5. [Unix] barrier->b = b でポインタ設定

uv_barrier_wait() [カスタム実装]:
1. mutex lock
2. while(out != 0) cond_wait（前回バリアの全スレッド離脱を待機）
3. in++
4. in == threshold?
   ├─ Yes: in=0, out=threshold, cond_broadcast（全スレッドに通知）
   └─ No: do cond_wait while(in != 0)（全到達を待機）
5. out--
6. out == 0? → cond_broadcast（destroyや次の使用を許可）
7. mutex unlock
8. last（out==0だったか）を返却

uv_barrier_init() [ネイティブ]:
1. pthread_barrier_init(barrier, NULL, count)

uv_barrier_wait() [ネイティブ]:
1. pthread_barrier_wait(barrier)
2. PTHREAD_BARRIER_SERIAL_THREAD → 非0を返却、それ以外は0
```

### フローチャート

```mermaid
flowchart TD
    A[uv_barrier_wait] --> B[mutex lock]
    B --> C{out != 0?}
    C -->|Yes| D[cond_wait: 前回離脱待ち]
    D --> C
    C -->|No| E[in++]
    E --> F{in == threshold?}
    F -->|Yes| G[in=0, out=threshold]
    G --> H[cond_broadcast]
    F -->|No| I[cond_wait: 全到達待ち]
    I --> J{in == 0?}
    J -->|No| I
    J -->|Yes| K[out--]
    H --> K
    K --> L{out == 0?}
    L -->|Yes| M[cond_broadcast + last=true]
    L -->|No| N[last=false]
    M --> O[mutex unlock]
    N --> O
    O --> P[last返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-136-01 | 最終到達スレッド | 最後にバリアに到達したスレッドのwait()は非0（真）を返す | 常時 |
| BR-136-02 | カスタム実装対象 | AIX/OpenBSD/Windows等、PTHREAD_BARRIER_SERIAL_THREAD未定義の環境ではカスタム実装 | 該当プラットフォーム |
| BR-136-03 | 再利用保護 | カスタム実装ではout変数により前回バリアの全離脱を確認してから次のバリアを開始 | カスタム実装 |
| BR-136-04 | destroy安全性 | destroy()はall out後のみ安全（in==0かつout==0の状態） | 常時 |

### 計算ロジック

カスタム実装のバリアロジック: in変数は到達スレッド数、out変数は離脱待ちスレッド数、thresholdは参加スレッド数。inがthresholdに達するとin=0, out=thresholdに設定し全スレッドに通知。各スレッドがout--で離脱。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | パラメータエラー | barrier==NULL、count==0 | 正しいパラメータで再呼び出し |
| UV_ENOMEM | メモリ不足 | カスタム実装でmalloc失敗 | メモリ確保後に再試行 |
| abort() | 致命的エラー | ネイティブ実装でpthread_barrier_waitが予期しないエラー、destroy失敗 | プログラムを修正 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

ネイティブpthread_barrierはカーネル最適化されている。カスタム実装はmutex+condvarベースのため若干のオーバーヘッドがあるが、バリア操作自体が低頻度であるため影響は小さい。

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

特になし。

## 備考

- カスタム実装のuv_barrier_tはUnixではポインタ（barrier->b）で内部構造体を参照し、Windowsではインライン構造体として定義される。
- ネイティブ実装ではPTHREAD_BARRIER_SERIAL_THREADを返却値として最終スレッドを識別する。
- カスタム実装ではout変数のカウントダウンにより全スレッドの離脱を追跡し、再利用可能性を保証する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unix.h | `include/uv/unix.h` | uv_barrier_tの型定義（L141-158: カスタム/ネイティブの条件分岐） |
| 1-2 | win.h | `include/uv/win.h` | uv_barrier_tの構造体定義（L272-276: mutex+cond+in+out+threshold） |
| 1-3 | uv.h | `include/uv.h` | API宣言（L1874-1876） |

**読解のコツ**: Unix版のuv_barrier_tはPTHREAD_BARRIER_SERIAL_THREADが定義されている場合はpthread_barrier_t、未定義の場合はstruct _uv_barrier*（ポインタ）として定義される。Windows版はインライン構造体。

#### Step 2: カスタム実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread-common.c | `src/thread-common.c` | uv_barrier_init()カスタム実装（L38-82） |
| 2-2 | thread-common.c | `src/thread-common.c` | uv_barrier_wait()カスタム実装（L85-120） |
| 2-3 | thread-common.c | `src/thread-common.c` | uv_barrier_destroy()カスタム実装（L123-149） |

**主要処理フロー**:
- **L38-82 (init)**: barrier/countの検証 → malloc → in/out/threshold初期化 → mutex_init → cond_init
- **L85-120 (wait)**: mutex_lock → while(out!=0) wait → in++ → threshold判定 → broadcast/wait → out-- → last判定 → broadcast → unlock
- **L123-149 (destroy)**: mutex_lock → assert(in==0) → while(out!=0) wait → unlock → mutex_destroy → cond_destroy → free

#### Step 3: ネイティブ実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | thread-common.c | `src/thread-common.c` | ネイティブ実装（L153-175） |

**主要処理フロー**:
- **L153-155 (init)**: pthread_barrier_init(barrier, NULL, count)
- **L158-167 (wait)**: pthread_barrier_wait → PTHREAD_BARRIER_SERIAL_THREADなら非0返却、その他エラーでabort()
- **L170-173 (destroy)**: pthread_barrier_destroy失敗でabort()

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

```
uv_barrier_init(barrier, count) [カスタム]
    +-- パラメータ検証
    +-- [Unix] uv__malloc(sizeof(struct _uv_barrier))
    +-- b->in=0, b->out=0, b->threshold=count
    +-- uv_mutex_init(&b->mutex)
    +-- uv_cond_init(&b->cond)

uv_barrier_wait(barrier) [カスタム]
    +-- uv_mutex_lock(&b->mutex)
    +-- while(b->out != 0) uv_cond_wait()  // 前回バリア離脱待ち
    +-- b->in++
    +-- if(b->in == b->threshold)
    |       b->in=0, b->out=b->threshold
    |       uv_cond_broadcast()
    +-- else: do uv_cond_wait() while(b->in != 0)
    +-- last = (--b->out == 0)
    +-- if(last) uv_cond_broadcast()
    +-- uv_mutex_unlock(&b->mutex)
```

### データフロー図

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

barrier, count           --> init: 内部構造体初期化       --> 初期化済みバリア
barrier                  --> wait: スレッド到達・待機      --> 0(非最終) / 非0(最終)
barrier                  --> destroy: リソース解放         --> (なし)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言（L1874-1876） |
| unix.h | `include/uv/unix.h` | ヘッダ | uv_barrier_t型定義（L141-158） |
| win.h | `include/uv/win.h` | ヘッダ | uv_barrier_t型定義（L272-276） |
| thread-common.c | `src/thread-common.c` | ソース | バリア実装（カスタム+ネイティブ、L30-175） |
