# 機能設計書 52-アトミック操作

## 概要

本ドキュメントは、Julia のアトミック操作機能（`@atomic`, `@atomicswap`, `@atomicreplace`, `@atomiconce` マクロおよび `Threads.Atomic` 型）の機能設計を記述する。

### 本機能の処理概要

本機能は、マルチスレッド環境においてロックなしでスレッドセーフな変数操作を行うための仕組みを提供する。LLVM のアトミック命令に直接マッピングされ、ハードウェアレベルのアトミック操作によってデータ競合を防止する。フィールドレベルのアトミックアクセス（`@atomic` アノテーション付きフィールド）と、レガシーな `Threads.Atomic{T}` ラッパー型の両方をサポートする。

**業務上の目的・背景**: マルチスレッドプログラミングにおいて、共有データへの安全なアクセスはデータ競合やメモリ破壊を防ぐために不可欠である。ロック（ReentrantLock など）は安全だがオーバーヘッドが大きく、単純なカウンタ更新やフラグ操作には不向きである。アトミック操作は、ロックを使わずにハードウェアレベルで不可分な操作を保証し、高パフォーマンスなスレッド間同期を実現する。

**機能の利用シーン**: 並列処理中のカウンタのインクリメント、ロックフリーデータ構造の実装、フラグの原子的な設定/確認、compare-and-swap ベースの楽観的並行制御、メモリオーダリングの制御が必要な低レベル並行プログラミング。

**主要な処理内容**:
1. `@atomic` マクロによるフィールド/参照のアトミック読み書き・modify操作
2. `@atomicswap` マクロによるアトミック交換
3. `@atomicreplace` マクロによるアトミック比較交換（CAS）
4. `@atomiconce` マクロによる条件付きアトミック初回代入
5. `Threads.Atomic{T}` 型による従来型のアトミック変数ラッパー
6. `atomic_cas!`, `atomic_add!`, `atomic_sub!` 等のアトミック演算関数
7. `atomic_fence`, `atomic_fence_light`, `atomic_fence_heavy` によるメモリフェンス

**関連システム・外部連携**: LLVM のアトミック命令（`cmpxchg`, `atomicrmw`, `fence`）に直接マッピング。OS カーネルのメモリバリア機能（`atomic_fence_heavy` は `jl_membarrier` ccall）。

**権限による制御**: 特に権限制御は行われない。

## 関連画面

本機能は GUI 画面を持たないライブラリ機能であり、直接的に関連する画面はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | REPL からアトミック操作を呼び出して使用 |

## 機能種別

計算処理（スレッドセーフな変数操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| x | Atomic{T} / @atomic フィールド / AtomicMemory | Yes | アトミック操作の対象 | @atomic アノテーション付きフィールドまたは Atomic{T} 型 |
| order | Symbol（QuoteNode） | No | メモリオーダリング。デフォルト :sequentially_consistent | :monotonic, :acquire, :release, :acquire_release, :sequentially_consistent のいずれか |
| val/new/cmp | T | 操作に依存 | 設定値、比較値、新値 | 対象フィールドの型 T に変換可能であること |
| op | Function | modify 操作時 | 二項演算関数（+, -, &, |, xor, max, min 等） | 二項演算子であること |

### 入力データソース

ユーザーコードから直接引数として渡される値。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @atomic 読み取り | T | フィールドの現在値 |
| @atomic 書き込み | T | 設定された新しい値 |
| @atomic modify | Pair{T,T} | (old, new) のペア |
| @atomicswap | T | 交換前の古い値 |
| @atomicreplace | NamedTuple{(:old,:success)} | 古い値と成功フラグ |
| @atomiconce | Bool | 代入が成功したかどうか |
| atomic_cas! | T | 古い値 |
| atomic_add!/sub!/and!/or!/xor!/nand!/max!/min! | T | 操作前の古い値 |

### 出力先

関数/マクロの戻り値として呼び出し元に返却。

## 処理フロー

### 処理シーケンス

```
1. マクロ展開フェーズ（コンパイル時）
   └─ @atomic / @atomicswap / @atomicreplace / @atomiconce の構文解析
   └─ メモリオーダリングの決定
   └─ 適切な内部関数呼び出しへの変換
     ├─ フィールドアクセス → getproperty/setproperty!/modifyproperty!/swapproperty!/replaceproperty!/setpropertyonce!
     └─ 参照アクセス → getindex_atomic/setindex_atomic!/modifyindex_atomic!/swapindex_atomic!/replaceindex_atomic!/setindexonce_atomic!
2. ランタイム実行フェーズ
   └─ LLVM アトミック命令の発行
   └─ ハードウェアレベルでの不可分操作の実行
   └─ メモリオーダリングに基づくメモリバリアの挿入
```

### フローチャート

```mermaid
flowchart TD
    A["@atomic 式"] --> B{式の種別判定}
    B -->|フィールド読み取り| C[getproperty with order]
    B -->|フィールド書き込み| D[setproperty! with order]
    B -->|modify 操作| E[modifyproperty! with order]
    B -->|参照読み取り| F[getindex_atomic with order]
    B -->|参照書き込み| G[setindex_atomic! with order]
    B -->|参照 modify| H[modifyindex_atomic! with order]
    C --> I[LLVM atomic load]
    D --> J[LLVM atomic store]
    E --> K[LLVM atomicrmw]
    F --> I
    G --> J
    H --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-1 | デフォルトオーダリング | 明示的なオーダリング指定がない場合、:sequentially_consistent が使用される | order 未指定時 |
| BR-52-2 | フィールドアノテーション | @atomic でアクセスするフィールドは型定義で `@atomic` アノテーションが必要 | mutable struct のフィールド |
| BR-52-3 | Atomic{T} 型制約 | Atomic{T} の T はプリミティブ型（数値型）に制限される | Threads.Atomic 使用時 |
| BR-52-4 | CAS セマンティクス | atomic_cas! は old === cmp の場合のみ new を書き込む | atomic_cas! 使用時 |
| BR-52-5 | 旧値返却 | atomic_add! 等の演算系関数は操作前の旧値を返す | 演算系アトミック関数使用時 |

### 計算ロジック

- `atomic_add!(x, v)`: `old = x[]; x[] = old + v; return old`（アトミックに実行）
- `atomic_cas!(x, cmp, new)`: `old = x[]; if old === cmp then x[] = new; return old`（アトミックに実行）
- `atomic_nand!(x, v)`: `old = x[]; x[] = ~(old & v); return old`（アトミックに実行）

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

該当なし。本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ErrorException | @atomic 式のパースに失敗 | 正しい @atomic 構文を使用 |
| - | ErrorException | @atomicswap に代入式がない | `@atomicswap a.x = val` の形式を使用 |
| - | ErrorException | @atomicreplace にフィールドアクセスがない | `@atomicreplace a.x old => new` の形式を使用 |
| - | ErrorException | @atomiconce に代入式がない | `@atomiconce a.x = val` の形式を使用 |
| - | TypeError | 値の型が対象フィールドの型と不一致 | 適切な型の値を使用 |

### リトライ仕様

CAS 操作のリトライは組み込みでは提供されない。ロックフリーアルゴリズムでは、ユーザーが CAS ループを自前で実装する必要がある。

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

個々のアトミック操作は不可分（atomic）であるが、複数のアトミック操作にまたがるトランザクションは提供されない。

## パフォーマンス要件

- アトミック操作はロックベースの同期と比較して低オーバーヘッド
- :sequentially_consistent はメモリバリアのコストが最も高い
- :monotonic / :acquire / :release はより軽量なオーダリング
- atomic_fence_light は atomic_fence より軽量（非対称フェンス）

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

アトミック操作自体にセキュリティリスクはないが、不正なメモリオーダリングの使用はデータ競合やメモリ破壊を引き起こす可能性がある。

## 備考

- Julia 1.7 でフィールドレベルのアトミック操作が導入された
- Julia 1.11 で @atomiconce が導入された
- Julia 1.12 で AtomicMemory の参照レベルアトミック操作が導入された
- `Threads.Atomic{T}` は旧 API で、新しいコードでは `@atomic` フィールドアノテーションの使用が推奨される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | atomics.jl | `base/atomics.jl` | Atomic{T} 構造体（41-45行目）: mutable struct で `@atomic value::T` フィールドを持つ。ゼロ初期化コンストラクタと値指定コンストラクタ |
| 1-2 | atomics.jl | `base/atomics.jl` | LOCK_PROFILING / LOCK_CONFLICT_COUNT（49-54行目）: ロックプロファイリング用のグローバル Atomic カウンタ |

**読解のコツ**: `@atomic` はフィールド定義時のアノテーション（型定義内）と、アクセス時のマクロ（式内）の二つの用法がある。型定義内の `@atomic` は `Expr(:atomic, ...)` に変換され、アクセス時の `@atomic` は `getproperty`/`setproperty!` 等に変換される。

#### Step 2: レガシー API（Threads.Atomic）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | atomics.jl | `base/atomics.jl` | getindex/setindex!（304-305行目）: Atomic の [] アクセスは @atomic :acquire/:release で実装 |
| 2-2 | atomics.jl | `base/atomics.jl` | atomic_cas! 〜 atomic_max!（306-315行目）: 全アトミック演算が @atomicreplace / @atomic / @atomicswap で実装 |
| 2-3 | atomics.jl | `base/atomics.jl` | atomic_fence / atomic_fence_light / atomic_fence_heavy（332-356行目）: メモリフェンス関数群 |

**主要処理フロー**:
- **304行目**: `getindex(x::Atomic) = @atomic :acquire x.value` - acquire セマンティクスでの読み取り
- **305行目**: `setindex!(x::Atomic, v) = (@atomic :release x.value = v; x)` - release セマンティクスでの書き込み
- **306行目**: `atomic_cas!(x, cmp, new) = (@atomicreplace :acquire_release :acquire x.value cmp => new).old`
- **307行目**: `atomic_add!(x, v) = (@atomic :acquire_release x.value + v).first`
- **332行目**: `atomic_fence() = Core.Intrinsics.atomic_fence(:sequentially_consistent, :system)`
- **347行目**: `atomic_fence_light() = Core.Intrinsics.atomic_fence(:sequentially_consistent, :singlethread)`
- **356行目**: `atomic_fence_heavy() = ccall(:jl_membarrier, Cvoid, ())`

#### Step 3: 新 API（@atomic マクロファミリー）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | expr.jl | `base/expr.jl` | @atomic マクロ（1414-1430行目）: 4つのオーバーロード（1引数/2引数/3引数/4引数）による構文解析 |
| 3-2 | expr.jl | `base/expr.jl` | make_atomic（1431-1484行目）: @atomic 式を適切な関数呼び出しに変換する内部関数 |
| 3-3 | expr.jl | `base/expr.jl` | @atomicswap マクロ（1534-1553行目）: アトミック交換の構文解析と変換 |
| 3-4 | expr.jl | `base/expr.jl` | @atomicreplace マクロ（1629-1663行目）: アトミック比較交換の構文解析と変換 |
| 3-5 | expr.jl | `base/expr.jl` | @atomiconce マクロ（1732-1756行目）: 条件付き初回代入の構文解析と変換 |

**主要処理フロー**:
- **1414-1418行目**: `@atomic ex` - 1引数：デフォルトオーダリングで make_atomic を呼び出し
- **1434行目**: フィールドアクセス `a.x` → `getproperty(a, :x, order)` に変換
- **1442行目**: 代入 `a.x = v` → `setproperty!(a, :x, v, order)` に変換
- **1449行目**: 参照アクセス `m[idx]` → `getindex_atomic(m, order, idx)` に変換
- **1478行目**: modify `a.x op v` → `modifyproperty!(a, :x, op, v, order)` に変換

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

```
@atomic 式
    │
    ├─ make_atomic(order, ex)
    │      ├─ フィールド読取 a.x → getproperty(a, :x, order)
    │      ├─ フィールド書込 a.x = v → setproperty!(a, :x, v, order)
    │      ├─ 参照読取 m[i] → getindex_atomic(m, order, i)
    │      ├─ 参照書込 m[i] = v → setindex_atomic!(m, order, v, i)
    │      └─ modify a.x op v → modifyproperty!(a, :x, op, v, order)
    │
    ├─ make_atomic(order, a1, op, a2)  [3引数 modify 形式]
    │      ├─ フィールド → modifyproperty!(a, :x, op, v, order)
    │      └─ 参照 → modifyindex_atomic!(m, order, op, v, i)
    │
@atomicswap 式
    └─ make_atomicswap(order, ex)
           ├─ フィールド → swapproperty!(a, :x, val, order)
           └─ 参照 → swapindex_atomic!(m, order, val, i)

@atomicreplace 式
    └─ make_atomicreplace(success_order, fail_order, ex, old_new)
           ├─ フィールド → replaceproperty!(a, :x, exp, rep, s_order, f_order)
           └─ 参照 → replaceindex_atomic!(m, s_order, f_order, exp, rep, i)

@atomiconce 式
    └─ make_atomiconce(success_order, fail_order, ex)
           ├─ フィールド → setpropertyonce!(a, :x, val, s_order, f_order)
           └─ 参照 → setindexonce_atomic!(m, s_order, f_order, val, i)

Threads.Atomic{T} [レガシー API]
    ├─ x[] → @atomic :acquire x.value
    ├─ x[] = v → @atomic :release x.value = v
    ├─ atomic_cas!(x, cmp, new) → @atomicreplace :acquire_release :acquire x.value cmp => new
    ├─ atomic_add!(x, v) → @atomic :acquire_release x.value + v
    └─ atomic_fence() → Core.Intrinsics.atomic_fence(:sequentially_consistent, :system)
```

### データフロー図

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

@atomic a.x          → getproperty(a, :x, order)    → 値 T
                         └→ LLVM atomic load

@atomic a.x = new    → setproperty!(a, :x, new, o)  → new
                         └→ LLVM atomic store

@atomic a.x + v      → modifyproperty!(a, :x, +, v) → (old, new)
                         └→ LLVM atomicrmw add

@atomicreplace a.x   → replaceproperty!(a, :x, ...)  → (old, success)
  old => new             └→ LLVM cmpxchg
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| atomics.jl | `base/atomics.jl` | ソース | Threads.Atomic{T} 型とレガシーアトミック関数の実装 |
| expr.jl | `base/expr.jl` | ソース | @atomic, @atomicswap, @atomicreplace, @atomiconce マクロの実装 |
| boot.jl | `base/boot.jl` | ソース | Core レベルのアトミック組み込み関数定義 |
| lock.jl | `base/lock.jl` | ソース | アトミック操作を内部的に使用するロック実装 |
| genericmemory.jl | `base/genericmemory.jl` | ソース | AtomicMemory 型の定義 |
