Files
hakorune/docs/説明書/reference/box-design/implementation-notes/socket-box-problem.md
Moe Charm e0f0a658e6 docs: Phase 9.75 Box設計根本革命 - SocketBox Arc<Mutex>責務一元化
 Phase 9.75実装計画追加:
- copilot_issues.txtにPhase 9.75追加(Phase 9.7と9.8の間)
- Arc<Mutex>二重化問題の根本解決計画
- 段階的実装戦略(Phase A-D)定義

📚 Box設計ドキュメント完全体系化:
- docs/説明書/reference/box-design/ 新設
- everything-is-box.md: 核心哲学の完全解説
- memory-management.md: Arc<Mutex>設計・fini/weak参照
- delegation-system.md: 完全明示デリゲーション仕様
- box-types-catalog.md: 全Box型の完全カタログ
- ffi-abi-specification.md: FFI/ABI仕様(移動済み)

🔧 実装ノート完備:
- current-issues.md: 現在進行中の設計課題
- socket-box-problem.md: Arc<Mutex>二重化問題詳細分析
- phase-9-75-redesign.md: 実装計画詳細

👥 Copilot実装ガイド作成:
- phase9_75_socketbox_arc_mutex_redesign.md
- SocketBox優先対応の具体的実装手順
- 完全テストスイート設計
- 段階的実装戦略(Step 1-5)

📋 CURRENT_TASK.md更新:
- Box設計ドキュメント完成記録
- Phase 9.75準備完了状況

🎯 効果:
- Everything is Box哲学の体系的文書化
- SocketBox問題解決の明確な道筋
- Copilot協調実装の準備完了
- 新規開発者オンボーディング改善

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 07:47:09 +09:00

5.2 KiB
Raw Blame History

🔌 SocketBox Arc二重化問題の詳細分析

🚨 問題の症状

観測された現象

// テストコード
server = new SocketBox()
server.bind("127.0.0.1", 8080)  // ✅ 成功: true
server.isServer()                // ❌ 失敗: false (期待値: true)

デバッグ出力

🔥 SOCKETBOX DEBUG: bind() called
🔥   Socket ID = 17
🔥   Arc pointer = 0x7ffd5b8a3d20
🔥   Arc data pointer = 0x5565423a6d60
🔥 AFTER MUTATION: is_server = true

🔥 SOCKETBOX DEBUG: isServer() called  
🔥   Socket ID = 17
🔥   Arc pointer = 0x7ffd5b8a3d20
🔥   Arc data pointer = 0x5565423a6d60  // 同じポインタ!
🔥 IS_SERVER READ: is_server = false   // しかし値は失われている

🔍 根本原因の分析

1. 責務の二重化

// 現在のSocketBox実装
pub struct SocketBox {
    base: BoxBase,
    listener: Arc<Mutex<Option<TcpListener>>>,  // 内部ロック
    stream: Arc<Mutex<Option<TcpStream>>>,      // 内部ロック
    is_server: Arc<Mutex<bool>>,                // 内部ロック
    is_connected: Arc<Mutex<bool>>,             // 内部ロック
}

// インタープリター側
let socket: Arc<Mutex<dyn NyashBox>> = Arc::new(Mutex::new(SocketBox::new()));

2. 状態更新の問題

// bind()メソッド内での状態更新
pub fn bind(&self, address: Box<dyn NyashBox>, port: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
    // ...
    *self.is_server.lock().unwrap() = true;  // 内部Mutexへの書き込み
    // ...
}

3. Clone実装の複雑性

impl Clone for SocketBox {
    fn clone(&self) -> Self {
        Self {
            base: BoxBase::new(),  // 新しいIDデバッグ用
            listener: Arc::clone(&self.listener),      // Arcを共有
            stream: Arc::clone(&self.stream),          // Arcを共有
            is_server: Arc::clone(&self.is_server),    // Arcを共有
            is_connected: Arc::clone(&self.is_connected), // Arcを共有
        }
    }
}

💀 デッドロックの危険性

発生パターン

  1. インタープリターがSocketBoxをロック
  2. SocketBoxメソッドが内部フィールドをロック
  3. 別スレッドが逆順でロックを試みる
  4. デッドロック発生

実際に観測されたデッドロック

// PR #75修正前
pub fn bind(&self, ...) -> Box<dyn NyashBox> {
    // ...
    let updated = SocketBox { /* ... */ };
    Box::new(updated.clone())  // ここでデッドロック
}

🔄 試みられた修正と結果

PR #75: Arc統合

目的: 状態を共有するためにArc参照を使用 結果:

  • デッドロック解消
  • 状態保持問題は未解決

PR #81: フィールド更新メカニズム

目的: インスタンスフィールドの更新を修正 結果:

  • フィールド更新は動作
  • SocketBox内部状態は依然として失われる

🎯 Gemini先生の根本解決策

設計原則の転換

// ❌ 現在の設計: Box自身がロック責務を持つ
pub struct SocketBox {
    is_server: Arc<Mutex<bool>>,  // Box内部でロック管理
}

// ✅ 新設計: 純粋なデータコンテナ
pub struct PlainSocketBox {
    pub listener: Option<TcpListener>,
    pub is_server: bool,  // シンプルなフィールド
}

責務の明確化

  • Box: 純粋なデータとロジックのみ
  • インタープリター: すべてのロック管理を一元化

実装例

// 新しいbind()実装
impl PlainSocketBox {
    pub fn bind(&mut self, addr: &str, port: u16) -> bool {
        match TcpListener::bind((addr, port)) {
            Ok(listener) => {
                self.listener = Some(listener);
                self.is_server = true;  // 直接代入、ロック不要
                true
            },
            Err(_) => false
        }
    }
}

📊 影響分析

同じ問題を抱えるBox型

  1. HTTPServerBox: SocketBoxを内包、同様の問題
  2. ArrayBox: Arc<Mutex<Vec<...>>>
  3. MapBox: Arc<Mutex<HashMap<...>>>
  4. P2PBox: 複雑な内部状態管理
  5. その他10個のBox型

リファクタリングの規模

  • 影響Box数: 15個
  • 推定作業量: 2-3週間Phase 9.75
  • リスク: 既存コードの互換性

🚀 移行戦略

Phase A: 設計ガイドライン3日

  1. 新Box実装パターンの確立
  2. Arc禁止ルールの明文化
  3. テンプレート・サンプルコード作成

Phase B: 最優先修正1週間

  1. SocketBox → PlainSocketBox
  2. HTTPServerBox → PlainHTTPServerBox
  3. 状態保持テストスイート作成

Phase C: 全Box統一1-2週間

  1. 残り13個のBox型修正
  2. 統合テスト実施
  3. パフォーマンス検証

🎉 期待される効果

  1. デッドロック根絶: 二重ロック構造の排除
  2. 状態整合性保証: インタープリター一元管理
  3. デバッグ容易性: シンプルな実装
  4. パフォーマンス向上: ロック競合の削減
  5. 保守性向上: 統一的な実装パターン

関連ドキュメント: