# 機能設計書: System.Threading（スレッディング）

## 1. 機能概要

### 1.1 機能名
System.Threading（スレッディング）

### 1.2 機能ID
FUNC-020

### 1.3 機能説明
.NET ランタイムにおけるマルチスレッド・並行処理機能を提供するライブラリ。スレッド管理、同期プリミティブ、スレッドプール、協調キャンセル、並行コレクションなど、マルチスレッドアプリケーション開発に必要な機能を包括的に提供する。Barrier、SpinLock、ReaderWriterLockSlim などの高度な同期機構も含む。

### 1.4 関連画面
- なし（基盤ライブラリのため直接的な関連画面は存在しない）

## 2. 機能要件

### 2.1 入力仕様

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| start | ThreadStart/ParameterizedThreadStart | No | スレッド開始デリゲート |
| waitHandle | WaitHandle | Yes | 待機ハンドル |
| timeout | int/TimeSpan | No | タイムアウト時間 |
| cancellationToken | CancellationToken | No | キャンセルトークン |
| participantCount | int | No | 参加者数（Barrier） |

### 2.2 出力仕様

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| bool | bool | 待機結果、ロック取得結果 |
| CancellationToken | CancellationToken | キャンセルトークン |
| Thread | Thread | スレッドオブジェクト |

### 2.3 処理フロー（Barrier）

```
Barrier(participantCount)
    │
    ▼
┌─────────────────────┐
│ 参加者登録           │
│ _currentTotalCount  │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ SignalAndWait()     │
│ 各参加者が到達を通知  │
└─────────────────────┘
    │
    ▼ 全員到達待ち
┌─────────────────────┐
│ フェーズ完了         │
│ PostPhaseAction実行 │
└─────────────────────┘
    │
    ▼
次のフェーズへ
```

## 3. 詳細設計

### 3.1 クラス構成

#### 3.1.1 スレッド管理

| クラス名 | 責務 |
|----------|------|
| Thread | スレッドの作成と管理 |
| ThreadPool | スレッドプール管理 |
| Timer | タイマーベースの定期実行 |

#### 3.1.2 同期プリミティブ

| クラス名 | 責務 |
|----------|------|
| Monitor | 排他ロック（lock文の基盤） |
| Mutex | プロセス間排他ロック |
| Semaphore/SemaphoreSlim | セマフォ |
| ReaderWriterLock/ReaderWriterLockSlim | 読み書きロック |
| SpinLock | スピンロック |
| SpinWait | スピン待機 |

#### 3.1.3 待機プリミティブ

| クラス名 | 責務 |
|----------|------|
| ManualResetEvent/ManualResetEventSlim | 手動リセットイベント |
| AutoResetEvent | 自動リセットイベント |
| CountdownEvent | カウントダウンイベント |
| Barrier | バリア同期 |

#### 3.1.4 協調キャンセル

| クラス名 | 責務 |
|----------|------|
| CancellationTokenSource | キャンセル要求の発行 |
| CancellationToken | キャンセル状態の監視 |

### 3.2 Barrier クラス（Barrier.cs）

#### 3.2.1 フィールドとビットマスク

```csharp
// Barrier.cs: 97-117行目
private volatile int _currentTotalCount;

// ビットマスク定義
private const int CURRENT_MASK = 0x7FFF0000;  // 現在のカウント
private const int TOTAL_MASK = 0x00007FFF;     // 総参加者数
private const int SENSE_MASK = unchecked((int)0x80000000);  // センスフラグ

private const int MAX_PARTICIPANTS = TOTAL_MASK;  // 最大32767

private long _currentPhase;
private bool _disposed;
private readonly ManualResetEventSlim _oddEvent;
private readonly ManualResetEventSlim _evenEvent;
private readonly ExecutionContext? _ownerThreadContext;
private readonly Action<Barrier>? _postPhaseAction;
private Exception? _exception;
private int _actionCallerID;
```

#### 3.2.2 コンストラクタ

```csharp
// Barrier.cs: 200-203行目
public Barrier(int participantCount)
    : this(participantCount, null)
{
}

// Barrier.cs: 219-237行目
public Barrier(int participantCount, Action<Barrier>? postPhaseAction)
{
    ArgumentOutOfRangeException.ThrowIfNegative(participantCount);
    ArgumentOutOfRangeException.ThrowIfGreaterThan(participantCount, MAX_PARTICIPANTS);
    _currentTotalCount = (int)participantCount;
    _postPhaseAction = postPhaseAction;

    _oddEvent = new ManualResetEventSlim(true);
    _evenEvent = new ManualResetEventSlim(false);

    if (postPhaseAction is not null)
    {
        _ownerThreadContext = ExecutionContext.Capture();
    }

    _actionCallerID = 0;
}
```

#### 3.2.3 プロパティ

```csharp
// Barrier.cs: 162-191行目
public int ParticipantsRemaining
{
    get
    {
        int currentTotal = _currentTotalCount;
        int total = (int)(currentTotal & TOTAL_MASK);
        int current = (int)((currentTotal & CURRENT_MASK) >> 16);
        return total - current;
    }
}

public int ParticipantCount
{
    get { return (int)(_currentTotalCount & TOTAL_MASK); }
}

public long CurrentPhaseNumber
{
    get { return Volatile.Read(ref _currentPhase); }
    internal set { Volatile.Write(ref _currentPhase, value); }
}
```

#### 3.2.4 参加者追加

```csharp
// Barrier.cs: 290-300行目
[UnsupportedOSPlatform("browser")]
public long AddParticipant()
{
    try
    {
        return AddParticipants(1);
    }
    catch (ArgumentOutOfRangeException)
    {
        throw new InvalidOperationException(SR.Barrier_AddParticipants_Overflow_ArgumentOutOfRange);
    }
}

// Barrier.cs: 321-388行目
[UnsupportedOSPlatform("browser")]
public long AddParticipants(int participantCount)
{
    ObjectDisposedException.ThrowIf(_disposed, this);
    ArgumentOutOfRangeException.ThrowIfNegativeOrZero(participantCount);
    ArgumentOutOfRangeException.ThrowIfGreaterThan(participantCount, MAX_PARTICIPANTS);

    if (_actionCallerID != 0 && Environment.CurrentManagedThreadId == _actionCallerID)
    {
        throw new InvalidOperationException(SR.Barrier_InvalidOperation_CalledFromPHA);
    }

    SpinWait spinner = default;
    long newPhase;
    while (true)
    {
        int currentTotal = _currentTotalCount;
        int total, current;
        bool sense;
        GetCurrentTotal(currentTotal, out current, out total, out sense);

        if (participantCount + total > MAX_PARTICIPANTS)
        {
            throw new ArgumentOutOfRangeException(nameof(participantCount), ...);
        }

        if (SetCurrentTotal(currentTotal, current, total + participantCount, sense))
        {
            // フェーズ計算と同期
            break;
        }
        spinner.SpinOnce(sleep1Threshold: -1);
    }
    return newPhase;
}
```

#### 3.2.5 SignalAndWait

```csharp
// Barrier.cs: 481-484行目
[UnsupportedOSPlatform("browser")]
public void SignalAndWait()
{
    SignalAndWait(CancellationToken.None);
}

// Barrier.cs: 625-758行目
[UnsupportedOSPlatform("browser")]
public bool SignalAndWait(int millisecondsTimeout, CancellationToken cancellationToken)
{
    ObjectDisposedException.ThrowIf(_disposed, this);
    cancellationToken.ThrowIfCancellationRequested();

    if (millisecondsTimeout < -1)
    {
        throw new System.ArgumentOutOfRangeException(nameof(millisecondsTimeout), ...);
    }

    if (_actionCallerID != 0 && Environment.CurrentManagedThreadId == _actionCallerID)
    {
        throw new InvalidOperationException(SR.Barrier_InvalidOperation_CalledFromPHA);
    }

    // メイン処理...
    SpinWait spinner = default;
    while (true)
    {
        currentTotal = _currentTotalCount;
        GetCurrentTotal(currentTotal, out current, out total, out sense);
        phase = CurrentPhaseNumber;

        if (total == 0)
        {
            throw new InvalidOperationException(SR.Barrier_SignalAndWait_InvalidOperation_ZeroTotal);
        }

        // 最後のスレッドの場合、フェーズ完了
        if (current + 1 == total)
        {
            if (SetCurrentTotal(currentTotal, 0, total, !sense))
            {
                FinishPhase(sense);
                return true;
            }
        }
        else if (SetCurrentTotal(currentTotal, current + 1, total, sense))
        {
            break;
        }

        spinner.SpinOnce(sleep1Threshold: -1);
    }

    // 他の参加者を待機
    ManualResetEventSlim eventToWaitOn = (sense) ? _evenEvent : _oddEvent;
    // ...
}
```

#### 3.2.6 FinishPhase

```csharp
// Barrier.cs: 765-802行目
private void FinishPhase(bool observedSense)
{
    if (_postPhaseAction is not null)
    {
        try
        {
            _actionCallerID = Environment.CurrentManagedThreadId;
            if (_ownerThreadContext is not null)
            {
                ContextCallback? handler = s_invokePostPhaseAction ??= InvokePostPhaseAction;
                ExecutionContext.Run(_ownerThreadContext, handler, this);
            }
            else
            {
                _postPhaseAction(this);
            }

            _exception = null;
        }
        catch (Exception ex)
        {
            _exception = ex;
        }
        finally
        {
            _actionCallerID = 0;
            SetResetEvents(observedSense);
            if (_exception is not null)
                throw new BarrierPostPhaseException(_exception);
        }
    }
    else
    {
        SetResetEvents(observedSense);
    }
}
```

### 3.3 CancellationTokenSource

```csharp
// キャンセルソース作成
var cts = new CancellationTokenSource();
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));  // タイムアウト付き

// キャンセル要求
cts.Cancel();
cts.CancelAfter(TimeSpan.FromSeconds(10));

// トークン取得
CancellationToken token = cts.Token;

// トークンの使用
token.ThrowIfCancellationRequested();
if (token.IsCancellationRequested) { ... }
token.Register(() => Console.WriteLine("Cancelled"));
```

### 3.4 SpinLock

```csharp
private SpinLock _lock = new SpinLock();

bool lockTaken = false;
try
{
    _lock.Enter(ref lockTaken);
    // クリティカルセクション
}
finally
{
    if (lockTaken)
        _lock.Exit();
}
```

### 3.5 ReaderWriterLockSlim

```csharp
private ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();

// 読み取りロック
_rwLock.EnterReadLock();
try { /* 読み取り */ }
finally { _rwLock.ExitReadLock(); }

// 書き込みロック
_rwLock.EnterWriteLock();
try { /* 書き込み */ }
finally { _rwLock.ExitWriteLock(); }
```

### 3.6 SemaphoreSlim

```csharp
private SemaphoreSlim _semaphore = new SemaphoreSlim(initialCount: 3, maxCount: 10);

await _semaphore.WaitAsync();
try
{
    // 制限付きリソースアクセス
}
finally
{
    _semaphore.Release();
}
```

## 4. エラー処理

### 4.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| OperationCanceledException | キャンセル要求時 |
| InvalidOperationException | 不正な状態での操作 |
| BarrierPostPhaseException | PostPhaseAction内での例外 |
| ObjectDisposedException | Dispose後の操作 |
| LockRecursionException | 再帰ロックエラー |
| SynchronizationLockException | ロック解除エラー |

### 4.2 BarrierPostPhaseException

```csharp
// Barrier.cs: 26-75行目
[Serializable]
public class BarrierPostPhaseException : Exception
{
    public BarrierPostPhaseException() : this((string?)null) { }
    public BarrierPostPhaseException(Exception? innerException)
        : this(null, innerException) { }
    public BarrierPostPhaseException(string? message)
        : this(message, null) { }
    public BarrierPostPhaseException(string? message, Exception? innerException)
        : base(message is null ? SR.BarrierPostPhaseException : message, innerException) { }
}
```

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

### 5.1 デッドロック防止
- ロック取得順序の統一
- タイムアウト付きロックの使用
- CancellationToken による協調キャンセル

### 5.2 レースコンディション対策
- 適切な同期プリミティブの選択
- Interlocked クラスによるアトミック操作
- volatile キーワードの適切な使用

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

### 6.1 推奨読解順序

1. **データ構造の理解**
   - `BarrierPostPhaseException`: フェーズ例外
   - ビットマスク定数の意味

2. **エントリーポイント**
   - `Barrier.cs`: バリア同期
   - **97-151行目**: フィールドとプロパティ
   - **200-237行目**: コンストラクタ
   - **290-388行目**: AddParticipant(s)
   - **481-758行目**: SignalAndWait
   - **765-802行目**: FinishPhase

3. **状態管理**
   - **246-251行目**: GetCurrentTotal ヘルパー
   - **261-271行目**: SetCurrentTotal ヘルパー
   - **818-832行目**: SetResetEvents

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

```
new Barrier(participantCount, postPhaseAction)
    │
    ├── 参加者数検証
    │
    ├── _currentTotalCount = participantCount
    │
    ├── _oddEvent = new ManualResetEventSlim(true)
    │
    └── _evenEvent = new ManualResetEventSlim(false)

barrier.SignalAndWait()
    │
    ├── ObjectDisposedException.ThrowIf(_disposed, this)
    │
    ├── SpinWait ループ
    │       │
    │       ├── GetCurrentTotal(currentTotal, ...)
    │       │
    │       └── SetCurrentTotal(currentTotal, current + 1, ...)
    │
    ├── if (current + 1 == total)
    │       │
    │       └── FinishPhase(sense)
    │               │
    │               ├── _postPhaseAction?.Invoke()
    │               │
    │               └── SetResetEvents(observedSense)
    │                       │
    │                       ├── CurrentPhaseNumber++
    │                       └── _oddEvent/_evenEvent Set/Reset
    │
    └── DiscontinuousWait(eventToWaitOn, ...)
```

### 6.3 データフロー図

```
┌──────────────────┐
│ 参加者スレッド 1   │
│ SignalAndWait()  │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ _currentTotalCount│
│ ├─ current++     │
│ └─ sense         │
└────────┬─────────┘
         │
    ┌────┴────┐
    ▼         ▼
まだ全員揃って  全員揃った
いない         （最後の到着者）
    │              │
    ▼              ▼
┌──────────┐  ┌──────────┐
│イベント待機│  │FinishPhase│
│(odd/even)│  │PHA実行   │
└──────────┘  └──────────┘
    │              │
    └──────┬───────┘
           ▼
┌──────────────────┐
│ 次フェーズへ進行   │
└──────────────────┘
```

### 6.4 読解のコツ

#### 6.4.1 ビットパッキング
_currentTotalCountは1つの整数で複数値を管理:
- 下位15ビット: 総参加者数
- 上位15ビット（シフト16）: 現在の到着者数
- 最上位ビット: センスフラグ（奇数/偶数フェーズ）

#### 6.4.2 センスフラグ
odd/evenイベントの交互使用でフェーズを区別:
```csharp
ManualResetEventSlim eventToWaitOn = (sense) ? _evenEvent : _oddEvent;
```

#### 6.4.3 PostPhaseAction保護
PHAからのAddParticipant等呼び出しを禁止:
```csharp
if (_actionCallerID != 0 && Environment.CurrentManagedThreadId == _actionCallerID)
{
    throw new InvalidOperationException(SR.Barrier_InvalidOperation_CalledFromPHA);
}
```

### 6.5 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/libraries/System.Threading/src/System/Threading/Barrier.cs` | ソース | バリア同期 |
| `src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs` | ソース | スレッド |
| `src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.cs` | ソース | スレッドプール |
| `src/libraries/System.Private.CoreLib/src/System/Threading/Monitor.cs` | ソース | モニター |
| `src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.cs` | ソース | ミューテックス |
| `src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.cs` | ソース | セマフォ |
| `src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs` | ソース | 軽量セマフォ |
| `src/libraries/System.Private.CoreLib/src/System/Threading/ReaderWriterLockSlim.cs` | ソース | RWロック |
| `src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs` | ソース | スピンロック |
| `src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs` | ソース | スピン待機 |
| `src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs` | ソース | キャンセルソース |
| `src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs` | ソース | キャンセルトークン |

## 7. 使用例

### 7.1 Barrier の使用

```csharp
var barrier = new Barrier(3, b =>
{
    Console.WriteLine($"Phase {b.CurrentPhaseNumber} completed");
});

var tasks = Enumerable.Range(0, 3).Select(i =>
    Task.Run(() =>
    {
        Console.WriteLine($"Thread {i}: Phase 1 work");
        barrier.SignalAndWait();

        Console.WriteLine($"Thread {i}: Phase 2 work");
        barrier.SignalAndWait();
    })).ToArray();

await Task.WhenAll(tasks);
barrier.Dispose();
```

### 7.2 CancellationToken の使用

```csharp
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

try
{
    await LongRunningOperationAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation was cancelled");
}

async Task LongRunningOperationAsync(CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        await Task.Delay(100, ct);
        // 処理...
    }
}
```

### 7.3 SemaphoreSlim の使用

```csharp
var semaphore = new SemaphoreSlim(3);

var tasks = Enumerable.Range(0, 10).Select(i =>
    Task.Run(async () =>
    {
        await semaphore.WaitAsync();
        try
        {
            Console.WriteLine($"Task {i} acquired");
            await Task.Delay(1000);
        }
        finally
        {
            semaphore.Release();
            Console.WriteLine($"Task {i} released");
        }
    })).ToArray();

await Task.WhenAll(tasks);
```

## 8. テスト観点

### 8.1 単体テスト観点
- 各同期プリミティブの基本動作
- タイムアウト処理の検証
- キャンセル処理の検証
- 例外発生時の動作

### 8.2 結合テスト観点
- 複数スレッドでの並行動作
- デッドロック検出
- レースコンディション検出

### 8.3 性能テスト観点
- ロック競合時のパフォーマンス
- スケーラビリティ測定
- メモリ使用量

## 9. 変更履歴

| バージョン | 日付 | 変更内容 |
|------------|------|----------|
| 1.0 | 2026-01-30 | 初版作成 |
