---
generated_at: 2026-01-23 10:35:00
metrics:
  claims_total: 42
  claims_with_evidence: 41
  claims_without_evidence: 1
confidence_derived: 0.98
---

# 根拠レポート: 信号システム（シグナル）

## 1. 概要

本レポートは「5-信号システム.md」機能設計書の記述内容について、ソースコードに基づく根拠を提示する。

## 2. 主張と根拠の対応

### 2.1 機能概要に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 1 | シグナルシステムはオブザーバーパターンを実装 | connect/emit_signalの実装がsubscriber/publisherパターン | object.cpp 1607-1674行目 |
| 2 | Object基底クラスにシグナル機能が実装されている | signal_map, connectionsがObjectクラスのメンバ | object.h 642-644行目 |
| 3 | シグナルの発行と接続により通信を実現 | emit_signalp(), connect()メソッドの存在 | object.cpp 1274-1432, 1607-1674行目 |

### 2.2 クラス構造に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 4 | SignalData構造体がスロット情報を保持 | `struct SignalData`の定義 | object.h 630-640行目 |
| 5 | Slot構造体にreference_count, conn, cEがある | `struct Slot`の定義 | object.h 631-635行目 |
| 6 | Connection構造体にsignal, callable, flagsがある | `struct Connection`の定義 | object.h 607-618行目 |
| 7 | signal_mapがHashMap<StringName, SignalData>型 | メンバ変数宣言 | object.h 643行目 |
| 8 | signal_mutexがMutex*型 | メンバ変数宣言 | object.h 642行目 |

### 2.3 接続フラグに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 9 | CONNECT_DEFERRED = 1 | enum ConnectFlags定義 | object.h 574行目 |
| 10 | CONNECT_PERSIST = 2 | enum ConnectFlags定義 | object.h 575行目 |
| 11 | CONNECT_ONE_SHOT = 4 | enum ConnectFlags定義 | object.h 576行目 |
| 12 | CONNECT_REFERENCE_COUNTED = 8 | enum ConnectFlags定義 | object.h 577行目 |
| 13 | CONNECT_APPEND_SOURCE_OBJECT = 16 | enum ConnectFlags定義 | object.h 578行目 |
| 14 | CONNECT_INHERITED = 32 | enum ConnectFlags定義 | object.h 579行目 |

### 2.4 connect()メソッドに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 15 | Callableがnullの場合エラーを返す | `ERR_FAIL_COND_V_MSG(p_callable.is_null(), ...)` | object.cpp 1608行目 |
| 16 | シグナルの存在をClassDBで確認 | `ClassDB::has_signal(get_class_name(), p_signal)` | object.cpp 1622行目 |
| 17 | スクリプトシグナルも確認する | `script_instance->get_script()->has_script_signal(p_signal)` | object.cpp 1625行目 |
| 18 | 重複接続時にREFERENCE_COUNTEDならカウント増加 | `slot_map[...].reference_count++` | object.cpp 1647行目 |
| 19 | 通常の重複接続はエラー | `ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, ...)` | object.cpp 1650行目 |
| 20 | ターゲットオブジェクトのconnectionsリストに追加 | `slot.cE = target_object->connections.push_back(conn)` | object.cpp 1664行目 |

### 2.5 emit_signalp()メソッドに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 21 | _block_signalsがtrueなら即座に返却 | `if (_block_signals) return ERR_CANT_ACQUIRE_RESOURCE` | object.cpp 1275-1277行目 |
| 22 | MAX_SLOTS_ON_STACK = 5でスタック最適化 | `constexpr int MAX_SLOTS_ON_STACK = 5` | object.cpp 1279行目 |
| 23 | 5スロット超過時はヒープ割り当て | `if (s->slot_map.size() > MAX_SLOTS_ON_STACK) { slot_callables = memalloc(...) }` | object.cpp 1302-1305行目 |
| 24 | ロック中にスロット情報をコピー | OBJ_SIGNAL_LOCKスコープ内でmemnew_placement | object.cpp 1288-1330行目 |
| 25 | ONE_SHOT接続はemit前に切断 | `if (slot_flags[i] & CONNECT_ONE_SHOT) { _disconnect(...) }` | object.cpp 1318-1329行目 |
| 26 | RefCountedオブジェクトはemit中保護される | `pending_unref = Object::cast_to<RefCounted>(this) ? ((RefCounted *)this)->reference() : false` | object.cpp 1339行目 |
| 27 | CONNECT_DEFERREDはMessageQueueに追加 | `MessageQueue::get_singleton()->push_callablep(...)` | object.cpp 1384行目 |
| 28 | 通常接続はcallable.callp()で直接呼び出し | `callable.callp(args, argc, ret, ce)` | object.cpp 1389行目 |
| 29 | _emittingフラグで発行中を追跡 | `_emitting = true; ... _emitting = false;` | object.cpp 1387, 1390行目 |

### 2.6 disconnect()メソッドに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 30 | reference_countが0より大きければ切断しない | `if (slot->reference_count > 0) return false` | object.cpp 1739-1741行目 |
| 31 | ターゲットのconnectionsリストからcEを削除 | `target_object->connections.erase(slot->cE)` | object.cpp 1747行目 |
| 32 | slot_mapから削除 | `s->slot_map.erase(*p_callable.get_base_comparator())` | object.cpp 1751行目 |
| 33 | 組み込みシグナルで空になったらSignalData削除 | `if (s->slot_map.is_empty() && ClassDB::has_signal(...)) signal_map.erase(...)` | object.cpp 1753-1756行目 |

### 2.7 スレッド安全性に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 34 | _ObjectSignalLockがRAIIでミューテックス管理 | コンストラクタでlock、デストラクタでunlock | object.cpp 68-84行目 |
| 35 | OBJ_SIGNAL_LOCKマクロでロック取得 | `#define OBJ_SIGNAL_LOCK _ObjectSignalLock _signal_lock_(this);` | object.cpp 64行目 |
| 36 | emit_signalp()でロック範囲を最小化 | スコープブレースでロック範囲を限定 | object.cpp 1288-1330行目 |

### 2.8 ユーザーシグナルに関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 37 | add_user_signal()でユーザーシグナル追加 | メソッド実装 | object.cpp 1209-1219行目 |
| 38 | 組み込みシグナルとの名前衝突をチェック | `ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), ...)` | object.cpp 1211行目 |
| 39 | _add_user_signal()はスクリプト用API | Array引数を受けてMethodInfo構築 | object.cpp 1444-1473行目 |
| 40 | removableフラグで削除可能性を管理 | `signal_map.getptr(p_name)->removable = true` | object.cpp 1471行目 |

### 2.9 API公開に関する主張

| No | 主張 | 根拠 | ソース |
|----|------|------|--------|
| 41 | connect/disconnect/is_connected/has_connectionsがバインドされている | ClassDB::bind_methodによる登録 | object.cpp 1985-1988行目 |
| 42 | emit_signalがvarargメソッドとしてバインド | bind_vararg_method使用 | object.cpp 1948-1954行目 |

## 3. 根拠なしの主張

| No | 主張 | 理由 |
|----|------|------|
| 1 | GDScriptでの使用例の構文 | GDScript実装はC++コードからは直接確認不可（ただし一般的な使用法として妥当） |

## 4. 信頼度評価

### 4.1 評価基準

- 全42主張中41主張にソースコード根拠あり
- 根拠なし1件はGDScript構文例（設計書として許容範囲）
- 全ての重要な技術的主張は行番号付きで検証済み

### 4.2 最終信頼度

**信頼度: 98%**

## 5. 検証に使用したソースファイル

| ファイル | 確認行数 | 検証項目数 |
|----------|----------|------------|
| core/object/object.cpp | 1-2000 | 28 |
| core/object/object.h | 1-1200 | 14 |

## 6. 特記事項

### 6.1 コード品質の観察

1. **スタック最適化**: emit_signalp()で5スロット以下はスタック使用という最適化が確認された
2. **ロック範囲最小化**: コピー後にロック解放という設計が確認された
3. **RefCounted保護**: emit中のオブジェクト破棄防止機構が実装されている

### 6.2 設計パターンの確認

- オブザーバーパターンの典型的な実装
- RAIIパターンによるミューテックス管理
- スモールバッファ最適化（スタック/ヒープ切り替え）
