# 機能設計書 133-読み書きロック

## 概要

uv_rwlock_init()/uv_rwlock_destroy()/uv_rwlock_rdlock()/uv_rwlock_tryrdlock()/uv_rwlock_rdunlock()/uv_rwlock_wrlock()/uv_rwlock_trywrlock()/uv_rwlock_wrunlock()により読み書きロック（Read-Write Lock）を制御する機能の設計書である。

### 本機能の処理概要

本機能は、複数スレッドが共有リソースに対して読み取り操作は並行して行い、書き込み操作は排他的に行うための同期プリミティブを提供する。

**業務上の目的・背景**：読み取り頻度が高く書き込み頻度が低いデータ構造（設定情報、キャッシュ、ルーティングテーブルなど）へのアクセスにおいて、ミューテックスでは読み取り同士も排他制御されるため不必要なスループット低下が発生する。読み書きロックにより、複数スレッドが同時に読み取りを行いつつ、書き込み時のみ排他制御を行うことでパフォーマンスを向上させる。libuvはPOSIXのpthread_rwlockとWindowsのSRWLock（Slim Reader/Writer Lock）の差異を吸収し、統一的なAPIを提供する。

**機能の利用シーン**：読み取り主体のキャッシュデータへの並行アクセス制御、設定情報の動的更新と参照の制御、イベントハンドラの登録・削除と走査の同期制御に利用される。libuv内部ではcloexec_lockとして使用されている。

**主要な処理内容**：
1. uv_rwlock_init()による読み書きロックの初期化
2. uv_rwlock_destroy()による読み書きロックの破棄
3. uv_rwlock_rdlock()/tryrdlock()/rdunlock()による読み取りロックの取得・解放
4. uv_rwlock_wrlock()/trywrlock()/wrunlock()による書き込みロックの取得・解放

**関連システム・外部連携**：Unix系ではpthread_rwlock_*系関数、WindowsではSRWLock系関数（AcquireSRWLockShared/Exclusive等）をラップする。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | スレッド | 主機能 | uv_rwlock_init()/destroy()/rdlock()/wrlock()等のAPI定義 |

## 機能種別

同期プリミティブ操作（読み書きロック制御）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rwlock | uv_rwlock_t* | Yes | 読み書きロックオブジェクト | NULLの場合は未定義動作 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 (init) | int | 成功時0、失敗時負のエラーコード |
| 戻り値 (tryrdlock/trywrlock) | int | 成功時0、ロック取得失敗時UV_EBUSY |
| 戻り値 (その他) | void | 失敗時abort()によりプロセス強制終了 |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
uv_rwlock_init():
1. [Unix] pthread_rwlock_init(rwlock, NULL)
2. [Windows] memset(rwlock, 0, sizeof(*rwlock)) + InitializeSRWLock()

uv_rwlock_rdlock():
1. [Unix] pthread_rwlock_rdlock(rwlock) → 失敗時abort()
2. [Windows] AcquireSRWLockShared()

uv_rwlock_tryrdlock():
1. [Unix] pthread_rwlock_tryrdlock(rwlock) → EBUSY/EAGAIN: UV_EBUSY、その他: abort()
2. [Windows] TryAcquireSRWLockShared() → 失敗: UV_EBUSY

uv_rwlock_wrlock():
1. [Unix] pthread_rwlock_wrlock(rwlock) → 失敗時abort()
2. [Windows] AcquireSRWLockExclusive()

uv_rwlock_trywrlock():
1. [Unix] pthread_rwlock_trywrlock(rwlock) → EBUSY/EAGAIN: UV_EBUSY、その他: abort()
2. [Windows] TryAcquireSRWLockExclusive() → 失敗: UV_EBUSY

uv_rwlock_rdunlock() / uv_rwlock_wrunlock():
1. [Unix] pthread_rwlock_unlock(rwlock) → 失敗時abort()
2. [Windows] ReleaseSRWLockShared() / ReleaseSRWLockExclusive()
```

### フローチャート

```mermaid
flowchart TD
    A[rwlock操作要求] --> B{操作種別}
    B -->|rdlock| C[読み取りロック取得]
    B -->|wrlock| D[書き込みロック取得]
    B -->|tryrdlock| E{読み取りロック試行}
    B -->|trywrlock| F{書き込みロック試行}
    E -->|成功| G[0を返却]
    E -->|失敗| H[UV_EBUSYを返却]
    F -->|成功| G
    F -->|失敗| H
    C --> I[ブロッキング待機後ロック取得]
    D --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-133-01 | 読み取り並行性 | 複数スレッドが同時に読み取りロックを保持可能 | 書き込みロックが保持されていない場合 |
| BR-133-02 | 書き込み排他性 | 書き込みロック保持中は他の読み取り・書き込みロック取得がブロックされる | 書き込みロック保持中 |
| BR-133-03 | 致命的エラー | rdlock/wrlock/rdunlock/wrunlock/destroyの失敗はabort()による即時終了 | 常時 |
| BR-133-04 | Windows SRWLock | WindowsではSRWLockを使用し、destroyは何もしない（不要） | Windows環境 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EBUSY | ロック競合 | tryrdlock/trywrlockで競合発生 | リトライまたは別処理を行う |
| abort() | 致命的エラー | lock/unlock/destroyでの内部エラー | プログラムのロジックを修正する |

### リトライ仕様

tryrdlock/trywrlockがUV_EBUSYを返した場合、呼び出し元でリトライ可能。

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

該当なし。

## パフォーマンス要件

読み取りロックは非競合時にユーザースペースで完結する。WindowsのSRWLockはSlim実装により低オーバーヘッド。読み取り主体のワークロードでミューテックスよりも高いスループットを実現する。

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

デッドロック防止のため、rdlock→wrlockへのアップグレードは不可（読み取りロック保持中に書き込みロック取得を試みるとデッドロック）。

## 備考

- WindowsのSRWLockはdestroyが不要であり、uv_rwlock_destroy()は空関数となる。
- Unix版ではrdunlock/wrunlockの両方がpthread_rwlock_unlock()を呼び出す（POSIX rwlockのunlockは統一API）。
- ABI互換性のため、Windowsのuv_rwlock_tのサイズはSTATIC_ASSERTで検証されている（64bit: 80バイト、32bit: 48バイト）。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unix.h | `include/uv/unix.h` | uv_rwlock_tの型定義（L132: pthread_rwlock_tのtypedef） |
| 1-2 | win.h | `include/uv/win.h` | uv_rwlock_tの構造体定義（L267: SRWLOCK read_write_lock_メンバー含む） |
| 1-3 | uv.h | `include/uv.h` | API宣言（L1854-1861） |

**読解のコツ**: Unix版はpthread_rwlock_tの直接typedef、Windows版はSRWLOCKを含む構造体。Windows版のABIサイズはSTATIC_ASSERTで保証されている（src/win/thread.c L404-408）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread.c (Unix) | `src/unix/thread.c` | 全rwlock関数（L390-450） |

**主要処理フロー**:
- **L390-392 (init)**: pthread_rwlock_init(rwlock, NULL)
- **L395-398 (destroy)**: pthread_rwlock_destroy失敗でabort()
- **L401-404 (rdlock)**: pthread_rwlock_rdlock失敗でabort()
- **L407-418 (tryrdlock)**: EBUSY/EAGAINならUV_EBUSY、それ以外abort()
- **L421-424 (rdunlock)**: pthread_rwlock_unlock失敗でabort()
- **L427-430 (wrlock)**: pthread_rwlock_wrlock失敗でabort()
- **L433-444 (trywrlock)**: EBUSY/EAGAINならUV_EBUSY、それ以外abort()
- **L447-450 (wrunlock)**: pthread_rwlock_unlock失敗でabort()

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | thread.c (Win) | `src/win/thread.c` | 全rwlock関数（L410-457） |

**主要処理フロー**:
- **L410-415 (init)**: memset + InitializeSRWLock
- **L418-421 (destroy)**: 空関数（SRWLockはdestroy不要）
- **L424-426 (rdlock)**: AcquireSRWLockShared
- **L429-434 (tryrdlock)**: TryAcquireSRWLockShared、失敗時UV_EBUSY
- **L437-439 (rdunlock)**: ReleaseSRWLockShared
- **L442-444 (wrlock)**: AcquireSRWLockExclusive
- **L447-452 (trywrlock)**: TryAcquireSRWLockExclusive、失敗時UV_EBUSY
- **L455-457 (wrunlock)**: ReleaseSRWLockExclusive

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

```
uv_rwlock_rdlock(rwlock)
    +-- [Unix] pthread_rwlock_rdlock() → 失敗: abort()
    +-- [Windows] AcquireSRWLockShared()

uv_rwlock_wrlock(rwlock)
    +-- [Unix] pthread_rwlock_wrlock() → 失敗: abort()
    +-- [Windows] AcquireSRWLockExclusive()

uv_rwlock_rdunlock(rwlock)
    +-- [Unix] pthread_rwlock_unlock() → 失敗: abort()
    +-- [Windows] ReleaseSRWLockShared()

uv_rwlock_wrunlock(rwlock)
    +-- [Unix] pthread_rwlock_unlock() → 失敗: abort()
    +-- [Windows] ReleaseSRWLockExclusive()
```

### データフロー図

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

uv_rwlock_t* rwlock --> rdlock/wrlock()            --> ロック取得（ブロッキング）
                        tryrdlock/trywrlock()      --> 0 / UV_EBUSY
                        rdunlock/wrunlock()        --> ロック解放
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言（L1854-1861） |
| unix.h | `include/uv/unix.h` | ヘッダ | uv_rwlock_t型定義（L132） |
| win.h | `include/uv/win.h` | ヘッダ | uv_rwlock_t構造体定義（L267） |
| thread.c (Unix) | `src/unix/thread.c` | ソース | Unix版実装（L390-450） |
| thread.c (Win) | `src/win/thread.c` | ソース | Windows版実装（L410-457） |
