# 機能設計書 138-スレッドローカルストレージ

## 概要

uv_key_create()/uv_key_delete()/uv_key_get()/uv_key_set()によりスレッドローカルストレージ（TLS）を制御する機能の設計書である。

### 本機能の処理概要

本機能は、各スレッドが独立して値を保持できるスレッドローカルストレージのクロスプラットフォームAPIを提供する。

**業務上の目的・背景**：マルチスレッドプログラミングにおいて、グローバル変数を使用しつつ各スレッドが独立した値を持ちたいケースは多い。スレッドローカルストレージは、同一のキーに対して各スレッドが異なる値を設定・取得できる機構である。errnoのようなスレッド安全なグローバル変数の実現や、スレッド固有のコンテキスト情報の管理に不可欠である。libuvはPOSIXのpthread_key_*とWindowsのTls*の差異を吸収して統一APIを提供する。libuv内部ではuv__current_thread_keyとして、Windows版のスレッドID管理に使用されている。

**機能の利用シーン**：スレッド固有のコンテキストデータの管理、スレッドごとのバッファ・キャッシュの管理、ログ出力時のスレッド識別情報の保持に利用される。

**主要な処理内容**：
1. uv_key_create()によるTLSキーの作成
2. uv_key_delete()によるTLSキーの削除
3. uv_key_get()によるスレッド固有値の取得
4. uv_key_set()によるスレッド固有値の設定

**関連システム・外部連携**：Unix系ではpthread_key_create/delete/getspecific/setspecific、WindowsではTlsAlloc/TlsFree/TlsGetValue/TlsSetValueを使用する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | スレッド | 主機能 | uv_key_create()/delete()/get()/set()によるTLSのAPI定義 |

## 機能種別

同期プリミティブ操作（スレッドローカルストレージ）

## 入力仕様

### 入力パラメータ

#### uv_key_create()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | uv_key_t* | Yes | TLSキーオブジェクト | NULLの場合は未定義動作 |

#### uv_key_get() / uv_key_set() / uv_key_delete()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | uv_key_t* | Yes | TLSキーオブジェクト | NULLの場合は未定義動作 |
| value (setのみ) | void* | Yes | 設定する値（NULLも設定可能） | なし |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 (create) | int | 成功時0、失敗時負のエラーコード |
| 戻り値 (get) | void* | スレッド固有に設定された値（未設定時NULL） |
| 戻り値 (delete/set) | void | 失敗時abort() |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
uv_key_create():
1. [Unix] pthread_key_create(key, NULL)
   └─ デストラクタは指定しない
2. [Windows] TlsAlloc()
   └─ TLS_OUT_OF_INDEXES → UV_ENOMEM

uv_key_delete():
1. [Unix] pthread_key_delete(*key) → 失敗時abort()
2. [Windows] TlsFree(key->tls_index) → 失敗時abort()
   └─ key->tls_index = TLS_OUT_OF_INDEXESで無効化

uv_key_get():
1. [Unix] pthread_getspecific(*key) → 値を返却
2. [Windows] TlsGetValue(key->tls_index)
   └─ NULLかつGetLastError() != ERROR_SUCCESS → abort()

uv_key_set():
1. [Unix] pthread_setspecific(*key, value) → 失敗時abort()
2. [Windows] TlsSetValue(key->tls_index, value) → FALSE時abort()
```

### フローチャート

```mermaid
flowchart TD
    A[uv_key_create] --> B{プラットフォーム}
    B -->|Unix| C[pthread_key_create]
    B -->|Windows| D[TlsAlloc]
    D --> E{TLS_OUT_OF_INDEXES?}
    E -->|Yes| F[UV_ENOMEM返却]
    E -->|No| G[0返却]
    C --> H{成功?}
    H -->|Yes| G
    H -->|No| I[エラーコード返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-138-01 | デストラクタなし | uv_key_create()はデストラクタを設定しない（NULLを渡す） | 常時 |
| BR-138-02 | 初期値NULL | 作成直後のキーで各スレッドの値はNULL | 常時 |
| BR-138-03 | Windows無効化 | delete()後にtls_indexをTLS_OUT_OF_INDEXESに設定 | Windows |
| BR-138-04 | Windows NULLチェック | get()でNULLが返された場合、GetLastErrorでエラーとNULL値を区別 | Windows |
| BR-138-05 | 致命的エラー | delete/set/getでの失敗はabort() | 常時 |

### 計算ロジック

特になし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_ENOMEM | リソース不足 | Windows版でTLSスロットが枯渇 | 不要なキーをdeleteする |
| abort() | 致命的エラー | delete/set/getでの内部エラー | プログラムを修正 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

TLS操作はスレッドローカルなメモリアクセスのみで完結し、ロック不要のため極めて高速。

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

TLSに格納したデータはスレッド終了時に自動解放されないため（デストラクタなし）、メモリリークに注意が必要。

## 備考

- uv_key_create()ではデストラクタコールバックが設定されないため、TLSに格納したヒープメモリはスレッド終了前に手動で解放する必要がある。
- WindowsのTLSスロット数には上限があり（プロセスあたり約1088）、多数のキーを作成するとUV_ENOMEMとなる。
- libuv内部ではuv__current_thread_key（Windows版でのスレッドID追跡用）として使用されている。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | unix.h | `include/uv/unix.h` | uv_key_tの型定義（L135: pthread_key_t） |
| 1-2 | win.h | `include/uv/win.h` | uv_key_tの構造体定義（L280: DWORD tls_index含む） |
| 1-3 | uv.h | `include/uv.h` | API宣言（L1885-1888） |

**読解のコツ**: Unix版はpthread_key_tの直接typedef、Windows版はtls_indexを持つ構造体。Windows版ではdelete時にtls_indexをTLS_OUT_OF_INDEXESにリセットする点に注意。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | thread.c (Unix) | `src/unix/thread.c` | uv_key_create/delete/get/set（L877-896） |

**主要処理フロー**:
- **L877-879 (create)**: pthread_key_create(key, NULL)、デストラクタなし
- **L882-885 (delete)**: pthread_key_delete失敗でabort()
- **L888-890 (get)**: pthread_getspecific(*key)
- **L893-896 (set)**: pthread_setspecific(*key, value)失敗でabort()

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | thread.c (Win) | `src/win/thread.c` | uv_key_create/delete/get/set（L538-568） |

**主要処理フロー**:
- **L538-543 (create)**: TlsAlloc()、TLS_OUT_OF_INDEXES時UV_ENOMEM
- **L546-550 (delete)**: TlsFree()失敗でabort()、tls_indexをTLS_OUT_OF_INDEXESに設定
- **L553-562 (get)**: TlsGetValue()、NULL時にGetLastError()でエラー判定
- **L565-568 (set)**: TlsSetValue()失敗でabort()

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

```
uv_key_create(key)
    +-- [Unix] pthread_key_create(key, NULL)
    +-- [Windows] key->tls_index = TlsAlloc()

uv_key_get(key)
    +-- [Unix] return pthread_getspecific(*key)
    +-- [Windows] value = TlsGetValue(key->tls_index)
                  NULLかつGetLastError()!=SUCCESS → abort()

uv_key_set(key, value)
    +-- [Unix] pthread_setspecific(*key, value) → 失敗: abort()
    +-- [Windows] TlsSetValue(key->tls_index, value) → FALSE: abort()
```

### データフロー図

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

key                 --> create: TLSキー確保    --> 初期化済みキー
key                 --> get: スレッド固有値取得 --> void* 値
key, value          --> set: スレッド固有値設定 --> (なし)
key                 --> delete: TLSキー解放    --> (なし)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言（L1885-1888） |
| unix.h | `include/uv/unix.h` | ヘッダ | uv_key_t型定義（L135） |
| win.h | `include/uv/win.h` | ヘッダ | uv_key_t型定義（L280） |
| thread.c (Unix) | `src/unix/thread.c` | ソース | Unix版TLS実装（L877-896） |
| thread.c (Win) | `src/win/thread.c` | ソース | Windows版TLS実装（L538-568） |
